DeepSeek Harness 本地聊天记忆:按来源保存聊天原文,关键词 + 向量检索,可选大模型重排与检索摘要。源码公开,仅限非商用
浏览文件
main
分支
cli.js
29 行 · 1.7 KB历史下载| 1 | |
| 2 | import { readFileSync } from 'node:fs'; |
| 3 | import { RetrievalMemory } from './store.js'; |
| 4 | const args = process.argv.slice(2); |
| 5 | const value = name => { const i = args.indexOf(name); return i >= 0 ? args[i + 1] : undefined; }; |
| 6 | const dir = value('--dir'); |
| 7 | if (!dir || !args[0]) { |
| 8 | console.error('用法:companion-memory <import|search|stats|export> --dir 目录 [--namespace dsh] [--scope owner|group:号|private:号] [--user local-user]'); |
| 9 | process.exit(2); |
| 10 | } |
| 11 | const memory = new RetrievalMemory({ dir }); |
| 12 | try { |
| 13 | const command = args[0]; |
| 14 | const access = { namespace: value('--namespace') || 'dsh', scope: value('--scope') || 'owner', userId: value('--user') || 'local-user' }; |
| 15 | if (command === 'import') { |
| 16 | const file = value('--file'); if (!file) throw new Error('import 需要 --file JSONL'); |
| 17 | let count = 0; |
| 18 | for (const line of readFileSync(file, 'utf8').split(/\r?\n/).filter(Boolean)) { |
| 19 | const { sourceKey, createdAt, content, source } = JSON.parse(line); |
| 20 | memory.put({ ...access, sourceKey, createdAt, content, source }); count++; |
| 21 | } |
| 22 | console.log(JSON.stringify({ imported: count })); |
| 23 | } else if (command === 'search') console.log(JSON.stringify(await memory.search(value('--query') || '', { ...access, topK: Number(value('--top-k') || 8) }), null, 2)); |
| 24 | else if (command === 'stats') console.log(JSON.stringify(memory.stats(), null, 2)); |
| 25 | // JSONL, one record per line — the same shape `import` reads, so an export can be re-imported. |
| 26 | else if (command === 'export') for (const row of memory.export(access)) |
| 27 | console.log(JSON.stringify({ sourceKey: row.source_key, createdAt: row.created_at, content: row.content, source: row.source })); |
| 28 | else throw new Error('未知命令'); |
| 29 | } finally { memory.close(); } |

