当前版本的边界
BM25 对技术名词和明确关键词很有效,但面对“他更擅长产品落地还是算法研究”这类语义问题,单纯词项匹配可能漏掉相关片段。知识增加到博客、项目文档和代码后,也不能继续手工维护几个大段落。
混合检索路线
# 计划中的结构示意
keyword_docs = bm25_retriever.invoke(query)
semantic_docs = vector_retriever.invoke(query)
candidates = reciprocal_rank_fusion(
keyword_docs,
semantic_docs,
)
context = reranker.compress_documents(candidates, query)
第一步使用文本切分器将长文档切成带重叠的小块;第二步生成 Embedding 并存入向量库;第三步把 BM25 与向量结果融合;最后使用轻量重排序器保留最相关片段。
引用必须成为界面的一部分
Retriever 已经保留 source 元数据。下一版 SSE 除了文本 token,还会发送结构化引用事件:
event: source
data: {"id":"resume/project-linter-ai","title":"Linter+AI 应用平台"}
聊天框收到来源事件后,在答案底部展示可点击引用。这样访客可以区分“模型组织的表达”和“简历中真实存在的事实”。
记忆不是保存所有聊天
长期记忆只应保存明确授权的信息,例如用户偏好的回答长度。原始问题、联系方式和敏感内容不应默认持久化。对个人 Agent 来说,忘记同样是一项需要设计的能力。