本文档记录本地规范检索服务当前已经达成共识的需求和接口边界,作为后续讨论匹配算法、阈值、日志及实现方案的基础。
本文档同时记录第一版匹配算法、初始阈值和测试用例。后续可根据真实查询日志调整参数,但不得改变服务的职责边界。
施工方案审查 Agent(智能体)需要检查方案中引用规范的时效性。为减少 Web Search(网页搜索)的调用和等待时间,建设一个基于本地人工维护规范库的检索服务。
服务接收规范查询关键词,从本地规范库中检索相关规范,并返回最多 3 条候选。Agent(智能体)结合候选内容,自行判断引用规范的时效性。
本地规范库由人工维护,默认其中的数据准确可信。
data_trust(数据可信度)。服务只提供一个批量查询业务接口:
POST /v1/search
{
"keywords": [
"GB 50330-2013 建筑边坡工程技术规范",
"混凝土结构设计规范",
"GB 50330"
]
}
请求说明:
keywords(关键词列表)为必填数组,第一版每批允许 1~100 条。{
"results": [
{
"query": "GB 50330-2013 建筑边坡工程技术规范",
"candidates": [
{
"code": "GB 50330-2013",
"title": "建筑边坡工程技术规范",
"status": "现行",
"relation_text": "替代 GB 50330-2002",
"implement_date": "2014-06-01",
"match_score": 1.0
}
]
},
{
"query": "本地规范库中不存在的规范",
"candidates": []
}
]
}
响应说明:
results(查询结果列表)与请求中的查询顺序一致。query(原始查询)原样返回,方便调用方建立对应关系。candidates(候选列表)包含 0~3 条规范。resolution(解析状态)或 matched(是否命中)。每条候选规范当前返回以下字段:
| 字段 | 含义 |
|---|---|
code |
规范编号 |
title |
规范名称 |
status |
规范状态,例如现行、已作废、已废止 |
relation_text |
本地库中的替代情况原文 |
implement_date |
实施日期 |
match_score |
查询关键词与候选规范的匹配度 |
替代情况仅作为候选规范的附带信息原样返回,不参与匹配计算。
服务只使用以下内容进行匹配:
允许处理的典型查询包括:
GB 50330-2013。GB 50330。建筑边坡工程技术规范。GB 50330-2013 建筑边坡工程技术规范。当名称或不含年份的编号匹配到多个规范版本时,服务可以返回多个候选,但最多返回 3 条。
第一版使用以下字段建立检索索引:
csres_code(官方编号)。csres_normalized_code(标准化编号),作为编号别名使用。csres_title(规范名称)。query_keyword(原始采集关键词)不作为规范名称索引,避免采集页面标题、应用指南等噪声影响匹配。
每条查询先拆分为“规范编号”和“规范名称”两个部分。例如:
输入:《建筑边坡工程技术规范》GB 50330—2013
编号:GB 50330-2013
名称:建筑边坡工程技术规范
编号解析支持编号出现在文本开头、末尾或括号内。第一版约定每条关键词描述一项规范;如果一条关键词中包含多个规范编号,服务仍按相关度返回最多 3 条候选,但调用方应尽量提前拆分。
编号比较前进行以下处理:
编号匹配分级如下:
| 编号情况 | 编号匹配度 |
|---|---|
| 标准化后完整编号一致 | 1.00 |
| 两位年份与四位年份对应 | 0.98 |
编号主体和年份一致,但 GB/GB/T 等属性不同 |
0.93 |
| 编号主体一致,但查询缺少年份 | 0.90 |
| 查询缺少分册号、分部分号或年份 | 0.80 |
| 编号疑似存在一个字符错误,且年份一致 | 0.75 |
| 编号主体一致但年份不同 | 0.70 |
年份不同只降低编号匹配度,不直接淘汰候选。服务返回相关规范及其实际编号,由 Agent(智能体)判断查询年份是否错误。
名称比较前进行以下处理:
名称匹配依次考虑:
查询名称少于 6 个中文字符时,不启用宽松模糊匹配,只允许完全一致或完整包含匹配。短名称包含匹配必须按覆盖比例降低分数,避免“验收规程”等通用短语获得虚高匹配度。
第一版采用编号、名称双通道并行匹配:
这样既能召回类似 TG/T 5440-2018 与 JTG/T 5440-2018 的单字符编号错误,也能让 JGJ 18-2022查询看到名称完全一致的 JGJ 18-2012,最终由 Agent(智能体)判断编号冲突。
match_score(匹配度)采用 0~1的数值范围:
只有编号时:
match_score = 编号匹配度
只有名称时:
match_score = 名称匹配度
同时包含编号和名称时:
较高分 = max(编号匹配度, 名称匹配度)
较低分 = min(编号匹配度, 名称匹配度)
match_score = 较高分 × 70% + 较低分 × 30%
该公式保证编号或名称任一维度高度相关时仍可返回,同时在另一维度冲突时降低最终匹配度。服务不再设置名称兜底分数上限。
候选满足以下任一条件即可进入排序:
准入条件按两个通道独立判断,不使用最终加权分数淘汰单项高度相关的候选。
调用服务的 Agent(智能体)应遵守以下原则:
服务后台需要记录查询日志,最低包含:
日志用于:
第一版使用 JSONL(逐行结构化日志),每条子查询记录一行,至少包含:
日志文件使用 UTF-8(统一字符编码)写入。第一版不实现自动轮转,待实际运行后根据日志增长速度确定轮转和保留策略。
服务支持多个 HTTP(网络请求)并发访问。规范库在服务启动时加载到内存,查询阶段只读本地数据;单进程内日志写入使用线程锁保护。
第一版实现重点保证并发下不出现共享状态写坏的问题。匹配计算仍属于 CPU(计算密集型)工作,因此吞吐能力主要受单机 CPU(中央处理器)、Uvicorn(Python ASGI 服务)进程数和单批关键词数量影响。
当前建议:
| 编号 | 测试场景 | 示例查询 | 预期结果 |
|---|---|---|---|
| 1 | 完整编号和名称 | GB 50330-2013 建筑边坡工程技术规范 |
2013 版排第一,匹配度为 1.00 |
| 2 | 全角符号和多余空格 | GB 50330—2013 |
命中 GB 50330-2013 |
| 3 | 两位年份 | CJJ 69-95 |
命中 CJJ 69-1995 |
| 4 | 规范属性差异 | GB/T 6441-1986 |
可以召回 GB 6441-1986,匹配度低于精确编号 |
| 5 | 编号缺少年份 | GB 50330 |
返回本地库中相关年份版本,最多 3 条 |
| 6 | 名称对应多个版本 | 建筑边坡工程技术规范 |
返回同名版本,最多 3 条 |
| 7 | 名称错别字 | 绕结多孔砖和多孔砌块 |
可以召回“烧结多孔砖和多孔砌块” |
| 8 | 编号单字符错误且名称一致 | TG/T 5440-2018 公路隧道加固技术规范 |
召回 JTG/T 5440-2018,匹配度低于精确编号 |
| 9 | 编号年份冲突 | JTG D70/2-2014 公路隧道设计规范 |
可以返回名称相关的 JTG D70-2004,但匹配度应体现编号冲突 |
| 10 | 替代关系不参与查询 | 只输入一个仅出现在 relation_text 中的编号 |
不得因为替代关系召回规范 |
| 11 | 候选上限 | 名称或编号匹配到 4 条以上记录 | 只返回匹配度最高的 3 条 |
| 12 | 无匹配结果 | 本地规范库中不存在的规范 |
返回空候选列表 |
| 13 | 批量查询 | 一次输入多条关键词 | 结果数量和顺序与输入一致 |
| 14 | 日志记录 | 执行一次批量查询 | 每条子查询都有时间、查询内容、结果和耗时日志 |
| 15 | 文件编码 | 加载 UTF-8 或 GB18030 编码的规范清单 | 均可正确读取中文内容 |
| 16 | 名称相同但年份不同 | 钢筋焊接及验收规程JGJ 18-2022 |
返回 JGJ 18-2012供 Agent(智能体)判断,匹配度为 0.91 |
| 17 | 编号分隔符周围有空格 | GB / T 6441 - 1986 |
正确解析并召回 GB 6441-1986 |
| 18 | 通用短名称 | 验收规程 |
可以返回相关候选,但匹配度不得虚高到 0.90 以上 |