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.
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.
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.
python3.8 works). Standard library only./v1/chat/completions. llama.cpp's llama-server does.Qwen34B.sh (port 8080) and Qwen25_05B.sh (port 8081).--verbose.| 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.
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.
For every suggestion:
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.kind is fact unless the model says correction. A wrongly labelled correction would be always injected if approved, so check CORRECTION flags during review.importance is always 2; set it when approving.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.
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.
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.
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.
0 success (including "nothing new"), 1 a transcript could not be read or a chunk failed, 2 usage error.
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 | 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. |