This commit is contained in:
2026-08-11 14:21:19 +08:00
parent 7c25691959
commit b8662138a9
3 changed files with 8 additions and 7 deletions
BIN
View File
Binary file not shown.
+7 -6
View File
@@ -28,8 +28,8 @@ const (
ParsePollIntervalSeconds = 15 // 解析/标注任务轮询间隔
DefaultLlmHttpTimeout = 600 // LLM HTTP 客户端超时(秒):本地模型生成慢,且多请求排队时响应可超分钟级
MaxExtractTokens = 4096 // 知识抽取单次生成的 token 预算(防失控生成烧掉上下文)
DefaultLlmHttpTimeout = 600 // LLM HTTP 客户端超时(秒):本地模型生成慢,且多请求排队时响应可超分钟级
MaxExtractTokens = 24576 // 知识抽取单次生成预算(思考链+JSON;24576≈实测自然输出 20 倍,4 并发下不超 131072 共享上下文)
EmbedBatchSize = 16 // 单次向量化请求的文本批量
@@ -38,10 +38,11 @@ const (
AnnoMaxCandidates = 60 // 多数据集融合后的候选上限(喂给 LLM 判定)
AnnoMaxClauseChars = 2000 // 合同条款全文上限(超长截断,控制 prompt)
// 判定 prompt 上下文预算(本地 4B 模型 context 8192 token,须留生成余量)
AnnoJudgeMaxTokens = 1024 // 判定输出 token 上限(JSON 结果含 ≤3 条风险;须显式限制,防推理模型长思考烧光上下文)
AnnoJudgeCandidateChars = 300 // 判定 prompt 单候选条文截断字数(精确条文文本由 ContentFull 抽取,不依赖 prompt 全文
AnnoJudgePromptBudget = 1500 // 判定 prompt 候选块总字数预算(候选按 RRF 相关度降序贪心填充,超预算截断后续候选
// 生成预算=思考链+JSON:实测判定自然输出仅 ~1.1k token,24576 留 20 倍余量(截断物理上不可能);
// 且 4 并发×(prompt≤3k+24.5k)≈110k ≤ 131072 共享上下文,更高值(如 32768)会触发并发拒收
AnnoJudgeMaxTokens = 24576 // 判定输出 token 上限(JSON 结果含 ≤3 条风险
AnnoJudgeCandidateChars = 300 // 判定 prompt 候选条文截断字数(精确条文文本由 ContentFull 抽取,不依赖 prompt 全文
AnnoJudgePromptBudget = 1500 // 判定 prompt 候选块总字数预算(候选按 RRF 相关度降序贪心填充,超预算截断后续候选)
// 合同风险识别
RiskLevelHigh = "high" // 高风险(违反强制性规定、可能导致合同无效/赔偿)
+1 -1
View File
@@ -292,7 +292,7 @@ StartParsePollermain.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 上下文预算**:本地 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 引用编号受展示条数约束(越界引用丢弃)
- **判定 prompt 上下文预算**:本地 gemma-4-E4B 由 LocalAI 托管(`models/gemma-4-E4B.yaml`llama.cpp 后端 gRPC 上报错 `rpc error`),`context_size=131072`(模型上限,GGUF `gemma4.context_length`2026-08-11 起)**跨 4 个 parallel slot 共享**——上限按并发请求合计占用量算(曾以 16384 运行,4 并发全量被拒 `Context size has been exceeded`)。**思维链默认开启**(推理模型,2026-08-11 起按用户要求移除 `reasoning_effort: none`,思考内容写入 `reasoning` 字段;此前靠它+`thinking:false` 双关仍占 2.7k+ 字符)。**生成预算 `max_tokens=24576`**(判定与知识抽取同值,2026-08-11 起;此前判定 1024/抽取 4096,思考链会烧光预算导致 `content` 为空或 JSON 截断):实测 4 并发判定自然输出仅 ~900-1100 token(思考链 ~3k 字符),24576 为 ~20 倍余量、截断物理上不可能;并发核验 4×(prompt≤3k+24.5k)≈110k≤131072 且实测 4 并发全部通过,更高值(如 32768)在真实 prompt 下会触发共享上下文拒收。候选块按 `AnnoJudgePromptBudget=1500` 字总预算**贪心填充**(按 RRF 相关度降序,每条截 `AnnoJudgeCandidateChars=300` 字,首条保底入队,超预算截断后续候选)。条文精确文本不依赖 prompt 全文——`extractLawItem` 用未截断的 `ContentFull` 抽取;LLM 引用编号受展示条数约束(越界引用丢弃)
- **快照落库**mark 存命中 chunk 的法条快照(law_title=dataset 名、law_item=LLM 判定的法条编号、content=chunk 内容截断 800 字),标注结果不随语料变更失效
- **批量落库(禁逐条 SQL)**:条款插入与风险快照用 `Batch(100)` 多行 INSERTGoFrame 一次语句写 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」;溯源失败仅告警不阻断标注(展示增强,非判定依据)