修复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:
+4
-2
@@ -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
@@ -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
@@ -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)) # 输入框上方
|
||||
|
||||
Reference in New Issue
Block a user