From 3d4ffe053e094f398dc132d8a0a4e6b6b4258205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Tue, 11 Aug 2026 12:59:06 +0800 Subject: [PATCH] 1 --- data/business.db | Bin 8667136 -> 8667136 bytes 技术设计.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/data/business.db b/data/business.db index dd5b70057b65cf7e4edf4e43a40db34779ad20af..f909e997d86a3dc5ee91f511bd4c7bf2f8e05f3a 100644 GIT binary patch delta 14613 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 delta 7327 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 diff --git a/技术设计.md b/技术设计.md index 6ec4f47..81c7c74 100644 --- a/技术设计.md +++ b/技术设计.md @@ -292,7 +292,7 @@ StartParsePoller(main.go 启动,gtimer 单例 5 秒轮询,job 未结束不 - **条款切分**:按优先级探测三种行首正则(`第X条` / `\d+(.\d+)*[、..]` / `中文数字[、..]`),命中 ≥2 采用,否则整篇单条(title=「全文」);title=标记、content=标记行至下一标记全文 - **召回**:每 dataset 各调 `VecSearch(dsId, vec, 15)` + `FtsSearch(dsId, 分词截 200 字, 15)`,全局按 RRF(`1/(RrfK+rank+1)`) 融合截 `AnnoMaxCandidates=60`;候选 chunk 内容**批量加载**(`ListByIds` 一次 IN 查回内存映射,禁止逐条 GetOne——N+1);embedder 按 dataset 绑定的 embedding 配置构建并缓存;**无候选的条款视为完成**(跳过 LLM 调用,无 mark) - **判定**:单次 LLM 调用,prompt 含条款全文(截 `AnnoMaxClauseChars=2000`)+ 编号候选,输出 `{"marks":[{"cand_id":1,"law_item":"第四十四条","score":9,"reason":"..."}]}`;**law_item 由 LLM 判定输出**(法条编号,`第X条` 正则兜底提取);JSON 解析与 rerankByLLM 同套路(```json 提取 + 截首尾花括号);**不做门槛过滤,全部候选(含 0 分)按分降序保留** -- **判定 prompt 上下文预算**:本地 4B 模型 context 8192 token,60 候选 × 2000 字会把上下文撑爆(`Context size has been exceeded`)。三道闸(缺一不可):① **关闭思维链**——gemma-4-E4B 是推理模型,默认输出长思考链占输出 token(`extra["thinking"]=false`,与 kg_extract 同策略,池提交前预置);② **显式 `max_tokens=AnnoJudgeMaxTokens=1024`**——不传时服务端默认预算大,推理模型可无限思考烧穿上下文;③ 候选块按 `AnnoJudgePromptBudget=1500` 字总预算**贪心填充**(按 RRF 相关度降序,每条截 `AnnoJudgeCandidateChars=300` 字,首条保底入队,超预算截断后续候选)。条文精确文本不依赖 prompt 全文——`extractLawItem` 用未截断的 `ContentFull` 抽取;LLM 引用编号受展示条数约束(越界引用丢弃) +- **判定 prompt 上下文预算**:本地 gemma-4-E4B 由 LocalAI 托管(`models/gemma-4-E4B.yaml`,llama.cpp 后端 gRPC 上报错 `rpc error`),`context_size=16384` **跨 4 个 parallel slot 共享**——上限按并发请求合计占用量算,单发请求可用 ~16384,4 条并发判定(每条 prompt ~1500 + 输出 1024 ≈ 2657 token)合计 ~10k 也会超出(曾以 8192 运行,4 并发全量被拒 `Context size has been exceeded`;提至 16384 后单发余量充足)。两道闸(缺一不可):① **服务端关闭思维链**——gemma-4-E4B 是推理模型,默认输出长思考链且写入 `reasoning` 字段,烧光 `max_tokens` 预算导致 `content` 为空或 JSON 截断(`thinking:false` 只削弱不消除,实测仍占 2.7k+ 字符;`models/gemma-4-E4B.yaml` 配 `reasoning_effort: none` 才能完全关闭,作用于所有请求,应用侧 `DisableThinking()` 的 `thinking:false` 保留为通用兜底);② **显式 `max_tokens=AnnoJudgeMaxTokens=1024`**;③ 候选块按 `AnnoJudgePromptBudget=1500` 字总预算**贪心填充**(按 RRF 相关度降序,每条截 `AnnoJudgeCandidateChars=300` 字,首条保底入队,超预算截断后续候选)。条文精确文本不依赖 prompt 全文——`extractLawItem` 用未截断的 `ContentFull` 抽取;LLM 引用编号受展示条数约束(越界引用丢弃) - **快照落库**:mark 存命中 chunk 的法条快照(law_title=dataset 名、law_item=LLM 判定的法条编号、content=chunk 内容截断 800 字),标注结果不随语料变更失效 - **批量落库(禁逐条 SQL)**:条款插入与风险快照用 `Batch(100)` 多行 INSERT(GoFrame 一次语句写 100 行,8 列 ≈800 变量 < SQLite 999 上限);进行中/完成状态用 `UpdateStatuses`(WHERE id IN,≤100 分批)各刷一次;进度按**本地计数**每完成一条刷一次 `UpdateProgress`(不再逐条款 `ListByTask` 读库统计)。仅失败路径保留逐条 `UpdateStatus`(error_msg 各异的罕见路径,不批量) - **来源文件标注**:法条引用快照同时记录源文件名(`LawRef.source_file`,如「劳动合同法.pdf」)——law_title 只是 dataset 名(如「法律」),看不出出自哪部法文件,溯源到 chunk 才能定位。判定时按单表约束拆两条 SQL(`kb_chunk` 按 id 批量查 document_id、`kb_document` 按 id 批量查 filename,IN ≤100 分批)内存组装;界面「法律依据」与导出 HTML 显示「来源:xx.pdf」;溯源失败仅告警不阻断标注(展示增强,非判定依据)