📝 QWEN_PROPOSE_MANUAL.mdv4.6.0 · 2026-10-19

qwen_propose.py — Manual

Project: Project AI Chatbot Memstore Version: 1.1.0 Date: 2026-10-26 Another collaboration between Andrew.human and Claude.ai

Written to be read by people and by AI models.

What it is

A program that reads conversation transcripts, asks a local language model to suggest memory entries, checks the suggestions with plain code, and writes a JSON file for memstore.py propose. The model only suggests. Nothing here writes to the memstore database, and nothing goes live until the operator approves it in memstore.py.

Where to run it

Not on Live. Run qwen_propose.py on the machine that hosts the model (the Clone, where the llama.cpp servers run), then copy the proposals file to the VPS and run memstore.py propose there. No transcript text leaves your own machines.

Requirements

Profiles

Profile Model URL Chunk size Timeout per call
4b (default) Qwen3-4B http://127.0.0.1:8080/v1/chat/completions 2000 characters 3600 s
05b Qwen2.5-0.5B http://127.0.0.1:8081/v1/chat/completions 3000 characters 900 s

Any of --url, --model, --chunk-chars, --timeout you type overrides the profile.

Speed and quality: on the Clone the 4B generates about 1.3 to 1.7 tokens per second and reads a prompt at about 3 tokens per second, so a 2000-character chunk takes roughly 5 to 10 minutes. A long transcript means hours; run it in the background (nohup ... &) and watch the progress lines. The 0.5B is far faster but weak: expect it to suggest little, and expect the quote check to drop much of what it invents. Use it to test the plumbing, and the 4B for real work.

Usage

python3.8 qwen_propose.py chat1.md --out proposals_2026-10-26.json --verbose
python3.8 qwen_propose.py chat1.md --profile 05b --out proposals_05b_1.json --verbose
python3.8 qwen_propose.py chat1.md --operator-marker '^Human:' --assistant-marker '^Claude:' --out p3.json
Option Meaning
files One or more transcript files (.md or .txt).
--profile 4b|05b Settings for the model (table above). Default 4b.
--out FILE Proposals file to create. Default /root/memstore/proposals.json. Never overwritten: if it exists the program stops, so give each run a new name.
--url, --model, --chunk-chars, --timeout Override the profile.
--state FILE Remembers which transcripts were done, per model and file name, by content hash. Default /root/memstore/qwen_propose_state.json.
--force Reprocess transcripts even if unchanged.
--operator-marker RE, --assistant-marker RE Regular expressions for lines where each speaker starts. When given, only the operator's lines are shown to the model, so it cannot mistake the assistant's words for facts about the operator. Give both or neither.
--verbose Show each dropped suggestion and why.

Every run prints qwen_propose 1.1.0 (2026-10-26) once to stderr, then one line naming the profile settings in use, then one progress line per chunk.

What the program checks itself (no model involved)

For every suggestion:

  1. The quote must be at least 8 characters.
  2. The quote's words must appear in order in the transcript chunk (spacing and letter case may differ). If not, the suggestion is dropped. This is the main defence against a small model inventing things.
  3. The stored quote is the transcript's own wording, not the model's copy.
  4. The text must be non-empty and at most 300 characters.
  5. At most 10 suggestions are taken per chunk; repeats within a run are dropped.
  6. origin is always set to inferred, whatever the model says. Only the operator can treat something as stated, by typing it with memstore.py add.
  7. kind is fact unless the model says correction. A wrongly labelled correction would be always injected if approved, so check CORRECTION flags during review.
  8. importance is always 2; set it when approving.

Model replies

The model is told to answer with JSON only, and the request asks the server to enforce JSON. If the server refuses that request (HTTP error), the program retries once without it. The program also accepts JSON wrapped in prose or code fences, and removes any <think>...</think> block first. A reply with no usable JSON counts as a chunk failure.

If any chunk of a transcript fails (model unreachable, timeout, or unusable reply), that transcript is not recorded as done, so the next run retries it. The exit status is 1.

Already-processed record

The state file is keyed by model|file name. A transcript done with the 4B is therefore still processed when you run the 0.5B, and the reverse. A changed transcript (different content hash) is processed again.

Untrusted text

Transcript text is treated as data, marked with delimiters, and the model is told not to follow instructions inside it. A small model can still be fooled, so the real protection is the quote check plus your own review.

Output file

A JSON list in the format memstore.py propose reads, with source_id set to the transcript's file name (use memstore.py forget --source NAME to remove everything that came from one transcript). If nothing survives the checks, no file is created.

Exit codes

0 success (including "nothing new"), 1 a transcript could not be read or a chunk failed, 2 usage error.

Ordered shutdown

No service or background process is involved. The program starts, runs and exits. The model servers are yours to start and stop in order; stop the one you finished with before starting the other, as the Clone has limited memory.

Version history

Version Date Change
1.1.1 2026-10-27 Default --out and --state now live in /root/memstore (or $MEMDIR), not the folder you ran from.
1.1.0 2026-10-26 Added --profile 4b|05b. Fixed: the processed record ignored the model. Added JSON-only request with fallback, <think> removal, per-chunk progress lines.
1.0.0 2026-10-26 First release.