修复2个问题:退回裁剪+知识库只回复匹配句\n\n1. 裁剪退回c9acd7e版(cap_left=0.25)\n 0.35只截到时间戳,用户消息被切;0.25覆盖消息文字区域\n\n2. 知识库返回全文→只返回匹配问答段\n 原问题:名字.txt含2个Q&A,TF-IDF整文件匹配后返回全文\n 该方案:knowledge_base._parse_qa_segments解析文件为独立问答段\n 每段作为独立doc,auto_reply._get_answer优先返回doc.answer\n 用户问一句话,只回复对应答句,不塞全部内容

This commit is contained in:
youpaishidifu
2026-07-26 13:38:04 +08:00
parent af3b730106
commit e9d9551e3d
3 changed files with 69 additions and 10 deletions
+4 -2
View File
@@ -65,8 +65,10 @@ class AutoReply:
return {"platform": platform, "answer": answer, "sender": sender}
def _get_answer(self, platform: str, msg: str, doc: dict, score: float) -> str or None:
"""提取答案 + 防重复检查。"""
answer = doc["content"].strip()
"""提取答案 + 防重复检查。
优先返回 doc['answer'](Q&A 段),兜底用整段 content。
"""
answer = (doc.get("answer") or doc["content"]).strip()
if not answer:
return None
+62 -5
View File
@@ -27,6 +27,50 @@ class KnowledgeBase:
"""jieba 分词"""
return list(jieba.cut(text))
@staticmethod
def _parse_qa_segments(content: str) -> list:
"""解析 Q&A 格式文件为独立问答段。
格式:问题[N]:xxx\\n答:xxx
返回 [{"question": str, "answer": str, "raw": str}]
"""
segments = []
cur_q = []
cur_a = []
state = None # None, 'q', 'a'
def flush():
if not cur_q and not cur_a:
return
q = '\n'.join(cur_q).strip()
a = '\n'.join(cur_a).strip()
if q or a:
segments.append({
"question": q,
"answer": a,
"raw": f"问题:{q}\n答:{a}",
})
cur_q.clear()
cur_a.clear()
for line in content.split('\n'):
qm = re.match(r'^问题\d*\s*[::]\s*(.*)', line)
am = re.match(r'^答\s*[::]\s*(.*)', line)
if qm:
flush()
state = 'q'
cur_q.append(qm.group(1))
elif am:
state = 'a'
cur_a.append(am.group(1))
elif state == 'q':
cur_q.append(line)
elif state == 'a':
cur_a.append(line)
# else: 文件头空白/注释,忽略
flush()
return segments
def set_path(self, path: str):
self.root_path = path
self.reload()
@@ -45,11 +89,24 @@ class KnowledgeBase:
try:
content = fp.read_text("utf-8", errors="ignore")
title = fp.stem
self.docs.append({
"path": str(fp),
"title": title,
"content": content,
})
# 解析 Q&A 段
segments = self._parse_qa_segments(content)
if segments:
for seg in segments:
self.docs.append({
"path": str(fp),
"title": title,
"content": seg["raw"],
"answer": seg["answer"],
"question": seg["question"],
})
else:
# 非 Q&A 格式,整文件作为一段
self.docs.append({
"path": str(fp),
"title": title,
"content": content,
})
except Exception:
continue
+3 -3
View File
@@ -570,9 +570,9 @@ class MessageMonitor:
# 先切 QQ 到前台再截屏,避免 CMD 窗口遮挡→OCR 读到终端文字
self._ensure_foreground(hwnd)
time.sleep(0.15)
# 左边界 35%,从消息面板左侧开始(联系人/会话列表 / 消息面板分界约 55%)
# 但消息正文在面板左侧,因此稍左移 35% 覆盖消息文字左侧边缘
cap_left = int(left + win_w * 0.35)
# 左边界 25%,覆盖消息文字区域(他人消息在面板左侧)
# 从 c9acd7e 版本恢复:0.35 仅截到时间戳,0.25 才覆盖文字
cap_left = int(left + win_w * 0.25)
cap_top = top + max(40, int(win_h * 0.04)) # 标题栏下方
cap_right = int(left + win_w * 0.95) # 跳过滚动条
cap_bottom = bottom - max(100, int(win_h * 0.10)) # 输入框上方