feat: 新增多格式文件上传入库与认证体系
- 新增 JWT 认证模块,支持登录/注册/用户管理 - 新增文件上传接口,支持 .txt/.md/.html/.pdf/.docx 等格式解析入库 - 新增检索结果 AI 总结功能 - 新增文本去重缓存机制 - 新增全局认证夹具简化测试 - 新增配置项与环境变量支持 - 完善文档与测试覆盖
This commit is contained in:
@@ -40,6 +40,9 @@ class ParsedQuery(BaseModel):
|
||||
rewrite: str = Field(description="rewrite 后的 query")
|
||||
keywords: list[str] = Field(default_factory=list, description="提取的关键词")
|
||||
categories: list[CategoryHit] = Field(default_factory=list, description="命中类目列表")
|
||||
entities: list[str] = Field(default_factory=list, description="提取的实体(人名/产品/技术等)")
|
||||
intent: str = Field(default="", description="查询意图分类(如 查询/对比/操作/定义/排查)")
|
||||
time_range: str = Field(default="", description="时间范围(如 '2023年'、'最近一个月'),空表示无")
|
||||
parse_failed: bool = Field(default=False, description="LLM 输出解析是否失败")
|
||||
|
||||
|
||||
@@ -136,11 +139,28 @@ class QueryParser:
|
||||
logger.warning("query 解析失败:JSON 必填字段缺失或类型错误", query=query, output=raw[:200])
|
||||
return ParsedQuery(raw_query=query, rewrite=query, parse_failed=True)
|
||||
|
||||
# 扩展字段:实体/意图/时间范围(缺失或类型错误时降级为默认值,不触发 parse_failed)
|
||||
entities = data.get("entities", [])
|
||||
if not isinstance(entities, list):
|
||||
logger.warning("query 解析 entities 非列表,置空", query=query)
|
||||
entities = []
|
||||
intent = data.get("intent", "")
|
||||
if not isinstance(intent, str):
|
||||
logger.warning("query 解析 intent 非字符串,置空", query=query)
|
||||
intent = ""
|
||||
time_range = data.get("time_range", "")
|
||||
if not isinstance(time_range, str):
|
||||
logger.warning("query 解析 time_range 非字符串,置空", query=query)
|
||||
time_range = ""
|
||||
|
||||
return ParsedQuery(
|
||||
raw_query=query,
|
||||
rewrite=rewrite,
|
||||
keywords=[str(k) for k in keywords],
|
||||
categories=self._validate_categories(categories, query),
|
||||
entities=[str(e) for e in entities],
|
||||
intent=intent,
|
||||
time_range=time_range,
|
||||
)
|
||||
|
||||
async def parse_and_route(self, query: str) -> RouteDecision:
|
||||
@@ -178,17 +198,22 @@ class QueryParser:
|
||||
category_lines = [f"- {c.name}: {c.description}" for c in self.taxonomy if c.name != UNCATEGORIZED]
|
||||
category_block = "\n".join(category_lines)
|
||||
return (
|
||||
"你是搜索查询分析助手。请分析用户 query,完成三件事:\n"
|
||||
"你是搜索查询分析助手。请分析用户 query,完成以下事项:\n"
|
||||
"1. 判断 query 意图命中以下哪些知识类目,并给出每个类目的置信度(0~1 之间的小数);\n"
|
||||
"2. 将 query 改写为更适合检索的形式;\n"
|
||||
"3. 提取 query 的关键词。\n\n"
|
||||
"3. 提取 query 的关键词;\n"
|
||||
"4. 提取 query 中的实体(人名、产品名、技术名词、组织机构等);\n"
|
||||
"5. 判断 query 的查询意图,从 [查询, 对比, 操作, 定义, 排查] 中选最接近的一个;\n"
|
||||
"6. 提取 query 中的时间范围(如 '2023年'、'上个月'、'Q1'),无则留空字符串。\n\n"
|
||||
f"可选类目:\n{category_block}\n\n"
|
||||
"要求:\n"
|
||||
"- categories 中的 name 只能从上面的类目名中选择,不要输出其他名称;\n"
|
||||
"- 若没有明显命中的类目,categories 返回空列表;\n"
|
||||
"- entities 没有则返回空数组;\n"
|
||||
"- 只输出 JSON,不要输出任何其他内容。\n\n"
|
||||
'输出格式:{"categories": [{"name": "类目名", "confidence": 0.0}], '
|
||||
'"rewrite": "改写后的 query", "keywords": ["关键词"]}\n\n'
|
||||
'"rewrite": "改写后的 query", "keywords": ["关键词"], '
|
||||
'"entities": ["实体"], "intent": "查询", "time_range": ""}\n\n'
|
||||
f"用户 query:{query}"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user