128 lines
4.0 KiB
Python
128 lines
4.0 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""experience.py — 蛋蛋经验库自动模块
|
|||
|
|
- search(text): 按关键词自动检索相关经验(解决问题前注入上下文)
|
|||
|
|
- save(title, content): 自动编号保存经验 + 更新索引
|
|||
|
|
- list_experiences(): 经验列表(供索引/前端展示)
|
|||
|
|
"""
|
|||
|
|
import os, re, glob, time
|
|||
|
|
|
|||
|
|
EXP_DIR = os.path.expanduser("~/cang-ying/eererdan/experience")
|
|||
|
|
INDEX = os.path.join(EXP_DIR, "EED-EXPER-INDEX.hdlp")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _next_num():
|
|||
|
|
nums = []
|
|||
|
|
for f in glob.glob(os.path.join(EXP_DIR, "EED-EXPER-*.hdlp")):
|
|||
|
|
m = re.search(r"EED-EXPER-(\d+)", os.path.basename(f))
|
|||
|
|
if m:
|
|||
|
|
nums.append(int(m.group(1)))
|
|||
|
|
return max(nums) + 1 if nums else 1
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _read(path, limit=2000):
|
|||
|
|
try:
|
|||
|
|
with open(path, encoding="utf-8") as f:
|
|||
|
|
return f.read(limit)
|
|||
|
|
except Exception:
|
|||
|
|
return ""
|
|||
|
|
|
|||
|
|
|
|||
|
|
def list_experiences():
|
|||
|
|
"""经验列表(按编号倒序)。"""
|
|||
|
|
out = []
|
|||
|
|
for f in sorted(glob.glob(os.path.join(EXP_DIR, "EED-EXPER-*.hdlp")), reverse=True):
|
|||
|
|
head = _read(f, 600)
|
|||
|
|
title = ""
|
|||
|
|
m = re.search(r"^# (.*)$", head, re.M)
|
|||
|
|
if m:
|
|||
|
|
title = m.group(1).strip()
|
|||
|
|
summary = ""
|
|||
|
|
for line in head.split("\n"):
|
|||
|
|
line = line.strip()
|
|||
|
|
if line and not line.startswith("#") and not line.startswith(">"):
|
|||
|
|
summary = line[:120]
|
|||
|
|
break
|
|||
|
|
out.append({
|
|||
|
|
"num": os.path.basename(f).replace("EED-EXPER-", "").replace(".hdlp", ""),
|
|||
|
|
"title": title,
|
|||
|
|
"summary": summary,
|
|||
|
|
"file": os.path.basename(f),
|
|||
|
|
})
|
|||
|
|
return out
|
|||
|
|
|
|||
|
|
|
|||
|
|
def search(text, limit_chars=1200, min_hits=2):
|
|||
|
|
"""按关键词检索相关经验,返回注入文本(限长)。命中少于 min_hits 个关键词返回空。"""
|
|||
|
|
text = (text or "").lower()
|
|||
|
|
kws = re.findall(r"[\u4e00-\u9fa5]{2,}|[A-Za-z]{3,}", text)
|
|||
|
|
if not kws:
|
|||
|
|
return ""
|
|||
|
|
scored = []
|
|||
|
|
for f in glob.glob(os.path.join(EXP_DIR, "EED-EXPER-*.hdlp")):
|
|||
|
|
if os.path.basename(f) == "EED-EXPER-INDEX.hdlp":
|
|||
|
|
continue
|
|||
|
|
content = _read(f, 3000).lower()
|
|||
|
|
hits = sum(1 for k in kws if k in content)
|
|||
|
|
if hits >= min_hits:
|
|||
|
|
title = ""
|
|||
|
|
m = re.search(r"^# (.*)$", content, re.M)
|
|||
|
|
if m:
|
|||
|
|
title = m.group(1)
|
|||
|
|
scored.append((hits, title, os.path.basename(f)))
|
|||
|
|
scored.sort(reverse=True)
|
|||
|
|
if not scored:
|
|||
|
|
return ""
|
|||
|
|
out = ["【📚 相关经验自动调用(已验证,可直接复用)】"]
|
|||
|
|
total = 0
|
|||
|
|
for hits, title, fn in scored[:3]:
|
|||
|
|
seg = f"▪ {title}"
|
|||
|
|
total += len(seg) + 2
|
|||
|
|
if total > limit_chars:
|
|||
|
|
break
|
|||
|
|
out.append(seg)
|
|||
|
|
return "\n".join(out)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def save(title, content):
|
|||
|
|
"""自动编号保存经验,返回文件名。"""
|
|||
|
|
title = (title or "未命名经验").strip()[:60]
|
|||
|
|
num = _next_num()
|
|||
|
|
fn = os.path.join(EXP_DIR, "EED-EXPER-%03d.hdlp" % num)
|
|||
|
|
body = (
|
|||
|
|
"# EED-EXPER-%03d · %s\n\n"
|
|||
|
|
"> 保存: %s\n\n"
|
|||
|
|
"---\n\n%s\n" % (num, title, time.strftime("%Y-%m-%d %H:%M"), content)
|
|||
|
|
)
|
|||
|
|
with open(fn, "w", encoding="utf-8") as f:
|
|||
|
|
f.write(body)
|
|||
|
|
_update_index()
|
|||
|
|
return os.path.basename(fn)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _update_index():
|
|||
|
|
items = list_experiences()
|
|||
|
|
lines = [
|
|||
|
|
"# EED-EXPER-INDEX.hdlp · 经验库索引(自动维护)",
|
|||
|
|
"",
|
|||
|
|
"> 倒序 · 最新的在上面 · 蛋蛋醒来扫一眼就知道手里有什么牌",
|
|||
|
|
"",
|
|||
|
|
]
|
|||
|
|
for it in items:
|
|||
|
|
lines.append("- %s | %s" % (it["file"], it["title"]))
|
|||
|
|
try:
|
|||
|
|
with open(INDEX, "w", encoding="utf-8") as f:
|
|||
|
|
f.write("\n".join(lines) + "\n")
|
|||
|
|
except Exception:
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
import sys
|
|||
|
|
if len(sys.argv) > 1 and sys.argv[1] == "list":
|
|||
|
|
for it in list_experiences():
|
|||
|
|
print(it["num"], it["title"])
|
|||
|
|
elif len(sys.argv) > 2 and sys.argv[1] == "search":
|
|||
|
|
print(search(sys.argv[2]))
|
|||
|
|
else:
|
|||
|
|
print("用法: experience.py list | search <关键词>")
|