fix: Bug F 修复回复混合和缺失步骤问题
- 修改guide query合并逻辑,按parent guide分组sections - 根据查询关键词选择最相关的guide(url/图床→非正版guide,正版/官网→正版guide) - 避免混合不同guide的内容,确保第一步不被遗漏 - 测试验证:url查询返回URL操作方式,官网查询返回正版玩家操作方式
This commit is contained in:
+98
-18
@@ -795,31 +795,111 @@ class KnowledgeBase:
|
||||
doc_sections.insert(0, doc_sections.pop(best_idx))
|
||||
|
||||
# 从每个文档取前 1-2 个 section
|
||||
# ⭐ 修复:当查询是操作指南(如何/怎么/教程)时,合并同一文档的所有相关 section
|
||||
# ⭐ 修复:当查询是操作指南(如何/怎么/教程)时,合并同一文档同一 guide 的所有相关 section
|
||||
# 避免"如何通过官网更新皮肤"只返回最后一个步骤
|
||||
# ⭐ 避免混合不同 guide 的内容(如 url 方式和正版玩家方式混合)
|
||||
is_guide_query = any(w in query_stripped for w in ['如何', '怎么', '教程', '步骤', '操作', '指南'])
|
||||
if is_guide_query and len(doc_sections) > 1:
|
||||
# 检查是否为操作指南类文档(多个步骤 section)
|
||||
step_headings = {'1.', '2.', '3.', '4.', '5.', '步骤', '第一', '第二', '第三', '第四', '第五'}
|
||||
step_count = sum(1 for _, doc, _ in doc_sections if any(s in doc.get('heading', '') for s in step_headings))
|
||||
if step_count >= 3:
|
||||
# 合并所有步骤 section 的 body
|
||||
merged_body = ""
|
||||
for idx, doc, score in doc_sections:
|
||||
heading = doc.get('heading', '')
|
||||
body = doc.get('body', doc.get('content', ''))
|
||||
if body and len(body) > 10:
|
||||
merged_body += f"\n{heading}\n{body}\n"
|
||||
if merged_body:
|
||||
# 创建合并后的文档
|
||||
merged_doc = doc_sections[0][1].copy()
|
||||
merged_doc['body'] = merged_body.strip()
|
||||
merged_doc['content'] = merged_body.strip()
|
||||
# 删除 answer 字段,使用 body
|
||||
if 'answer' in merged_doc:
|
||||
del merged_doc['answer']
|
||||
results.append((merged_doc, float(doc_sections[0][2])))
|
||||
continue
|
||||
# ⭐ 获取最佳文档的路径,查找该文档的所有 sections
|
||||
best_doc_path = doc_sections[0][1].get('path', '')
|
||||
if best_doc_path:
|
||||
# 查找同一文档的所有 sections
|
||||
all_doc_sections = [(i, d) for i, d in enumerate(self.docs) if d.get('path') == best_doc_path]
|
||||
|
||||
if len(all_doc_sections) > 3: # 有多个 sections,可能是操作指南
|
||||
# ⭐ 按 parent guide 分组 sections
|
||||
# 遇到 # 或 ## 级别标题时,视为新 guide 的开始
|
||||
guides = [] # [(parent_heading, [(idx, doc), ...]), ...]
|
||||
current_guide = None
|
||||
current_sections = []
|
||||
|
||||
for idx, doc in all_doc_sections:
|
||||
heading = doc.get('heading', '')
|
||||
# 判断是否为 guide 级别标题(# 或 ##)
|
||||
if heading.startswith('# ') or heading.startswith('## '):
|
||||
# 保存前一个 guide
|
||||
if current_guide is not None and current_sections:
|
||||
guides.append((current_guide, current_sections))
|
||||
current_guide = heading
|
||||
current_sections = [(idx, doc)]
|
||||
else:
|
||||
# 属于当前 guide 的子 section(### 及以下)
|
||||
if current_guide is not None:
|
||||
current_sections.append((idx, doc))
|
||||
else:
|
||||
# 没有 guide 级别标题,作为独立 section
|
||||
if current_sections:
|
||||
guides.append((None, current_sections))
|
||||
current_sections = [(idx, doc)]
|
||||
current_guide = None
|
||||
|
||||
# 保存最后一个 guide
|
||||
if current_guide is not None and current_sections:
|
||||
guides.append((current_guide, current_sections))
|
||||
elif current_sections:
|
||||
guides.append((None, current_sections))
|
||||
|
||||
# 选择最相关的 guide 进行合并
|
||||
if len(guides) > 1:
|
||||
# ⭐ 根据查询关键词选择 guide
|
||||
# 查询含 "url"/"图床"/"直连"/"链接" → 选择非正版 guide(含 url 操作方式)
|
||||
# 查询含 "正版"/"官网"/"启动器"/"更新" → 选择正版 guide
|
||||
# 默认选择包含最多步骤的 guide
|
||||
url_keywords = {'url', '图床', '直连', '链接', '非正版'}
|
||||
genuine_keywords = {'正版', '官网', '启动器', 'minecraft.net'}
|
||||
|
||||
best_guide_idx = 0
|
||||
best_guide_score = -1
|
||||
|
||||
for i, (parent, sections) in enumerate(guides):
|
||||
if not sections:
|
||||
continue
|
||||
# 计算 guide 与查询的相关性
|
||||
guide_text = ' '.join(doc.get('heading', '') + ' ' + doc.get('body', '')
|
||||
for _, doc in sections)
|
||||
score = 0
|
||||
for kw in url_keywords:
|
||||
if kw in query_stripped and kw in guide_text:
|
||||
score += 10
|
||||
for kw in genuine_keywords:
|
||||
if kw in query_stripped and kw in guide_text:
|
||||
score += 10
|
||||
# 优先选择步骤最多的 guide(默认行为)
|
||||
step_in_guide = sum(1 for _, doc in sections
|
||||
if any(s in doc.get('heading', '') for s in step_headings))
|
||||
score += step_in_guide * 2
|
||||
|
||||
if score > best_guide_score:
|
||||
best_guide_score = score
|
||||
best_guide_idx = i
|
||||
|
||||
selected_guide = guides[best_guide_idx][1]
|
||||
else:
|
||||
# 只有一个 guide,直接使用
|
||||
selected_guide = guides[0][1] if guides else []
|
||||
|
||||
# 合并选中 guide 的所有步骤 section
|
||||
if selected_guide:
|
||||
merged_body = ""
|
||||
for idx, doc in selected_guide:
|
||||
heading = doc.get('heading', '')
|
||||
body = doc.get('body', doc.get('content', ''))
|
||||
if body and len(body) > 10:
|
||||
merged_body += f"\n{heading}\n{body}\n"
|
||||
if merged_body:
|
||||
# 创建合并后的文档
|
||||
merged_doc = selected_guide[0][1].copy()
|
||||
merged_doc['body'] = merged_body.strip()
|
||||
merged_doc['content'] = merged_body.strip()
|
||||
# 删除 answer 字段,使用 body
|
||||
if 'answer' in merged_doc:
|
||||
del merged_doc['answer']
|
||||
results.append((merged_doc, float(doc_sections[0][2])))
|
||||
continue
|
||||
|
||||
# 默认:从每个文档取前 1-2 个 section
|
||||
sub_k = 2 if len(results) < top_k - 1 else top_k - len(results)
|
||||
|
||||
Reference in New Issue
Block a user