86 lines
3.0 KiB
Python
86 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
TECH_OVERLAP_KEYWORDS = [
|
|
"报错", "日志", "配置", "接口", "插件", "部署", "docker", "python", "openclaw", "机器人", "qdrant", "ollama",
|
|
]
|
|
ANSWER_KEYWORDS = [
|
|
"先", "然后", "重启", "配置", "日志", "接口", "看一下", "试试", "排查",
|
|
"报错", "原因", "因为", "改成", "装", "部署", "重现", "检查", "确认",
|
|
]
|
|
|
|
|
|
def build_conversation_hints(
|
|
recent_messages: List[Dict],
|
|
current_sender: str,
|
|
current_content: str,
|
|
quote_context: Dict[str, Any],
|
|
bot_name: str,
|
|
) -> Dict[str, Any]:
|
|
previous_messages = list(recent_messages[:-1]) if recent_messages else []
|
|
recent_window = previous_messages[-4:]
|
|
solver_count = 0
|
|
solver_senders = set()
|
|
current_tokens = extract_overlap_tokens(current_content)
|
|
for item in recent_window:
|
|
sender = str(item.get("sender", "") or "")
|
|
if not sender or sender == current_sender:
|
|
continue
|
|
content = str(item.get("content") or item.get("message") or "").strip().lower()
|
|
if looks_like_answer(content) and has_topic_overlap(current_tokens, content):
|
|
solver_count += 1
|
|
solver_senders.add(sender)
|
|
|
|
previous_same_sender_directed = False
|
|
same_sender_recent_count = 0
|
|
bot_name_lower = str(bot_name or "").lower()
|
|
for item in reversed(previous_messages[-6:]):
|
|
sender = str(item.get("sender", "") or "")
|
|
if sender != current_sender:
|
|
continue
|
|
same_sender_recent_count += 1
|
|
content = str(item.get("content") or item.get("message") or "").strip().lower()
|
|
if bool(item.get("is_at")) or (bot_name_lower and bot_name_lower in content):
|
|
previous_same_sender_directed = True
|
|
break
|
|
|
|
quote_targets_bot = False
|
|
quote_sender_name = str(quote_context.get("quote_sender_name", "") or "").strip().lower()
|
|
if quote_sender_name and bot_name_lower and bot_name_lower in quote_sender_name:
|
|
quote_targets_bot = True
|
|
|
|
return {
|
|
"has_recent_human_solver": solver_count >= 2 and len(solver_senders) >= 1,
|
|
"solver_count": solver_count,
|
|
"previous_same_sender_directed": previous_same_sender_directed,
|
|
"same_sender_recent_count": same_sender_recent_count,
|
|
"quote_targets_bot": quote_targets_bot,
|
|
}
|
|
|
|
|
|
def looks_like_answer(content: str) -> bool:
|
|
if not content:
|
|
return False
|
|
if len(content) >= 18:
|
|
return True
|
|
return any(keyword in content for keyword in ANSWER_KEYWORDS)
|
|
|
|
|
|
def extract_overlap_tokens(content: str) -> set[str]:
|
|
text = str(content or "").lower()
|
|
tokens = set(re.findall(r"[a-z0-9_\\-]{3,}", text))
|
|
for keyword in TECH_OVERLAP_KEYWORDS:
|
|
if keyword in text:
|
|
tokens.add(keyword)
|
|
return tokens
|
|
|
|
|
|
def has_topic_overlap(current_tokens: set[str], previous_content: str) -> bool:
|
|
if not current_tokens:
|
|
return False
|
|
previous_tokens = extract_overlap_tokens(previous_content)
|
|
return bool(current_tokens & previous_tokens)
|