从赌约到透明AI(v1 -> v2):我如何让一个本地助手变得可审计、可调节、可解释
记忆可追溯、性格可调节、解释可分层的智能体是怎样炼成的
起点很荒诞,但我窥见了另一种可能性:当 AI 越来越流畅、越来越“像人”,我们是否正在被一种无法验证的信任所包围?它记得我上句话,我无法核实;它给出一个结论,我不知依据。于是“不透明 = 不存在”成了我设计系统的底层执念:如果用户不能亲手翻开记忆、不能调节性格、不能追溯推理链,那 AI 就不算真正存在。所以,我决定自己动手。
本文不谈论文,不谈数学推导,只谈工程。我会讲清楚从 v1(能跑就行)到 v1.5(可解释框架)再到 v2(事件驱动 + 元认知闭环)的每一次版本升级,我们到底解决了什么问题,以及为什么要把架构设计成现在的样子。
v1.0:从“能跑”到“能用”的奠基
目标:让AI“活”在本地,不被云服务绑架。
基础能力
- 基于 Ollama + Qwen2.5,实现基础对话、短期记忆、简单规则引擎。
- 引入 RAG 检索(ChromaDB),知识库可加载自定义文本(因为本地模型知识有限,需要外挂知识库才能回答专业问题)。
- 增加工具调用(时间、天气、计算、安全命令),支持多轮工具调用。
- 加入用户画像雏形:用户完成4题简易 MBTI 测试后,系统初始化八种认知功能的初始置信度。
透明性初探
- 记忆可追溯:每条记忆生成唯一 ID,侧边栏展示记忆列表,点击可查看完整内容。
- 强制引用:回答中引用的记忆必须附带 ID,用户可一键验证。
- 分层解释:实现简洁型、逻辑型(含 Mermaid 流程图)、调试型三种解释深度。
一个可用的透明底座
- 荣格八维认知功能(Ti/Te/Fi/Fe/Si/Se/Ni/Ne)作为风格引擎,用户可通过滑块实时调整置信度。
- 证据图雏形:将记忆、知识、工具调用统一为节点,初步构建推理链(虽未建立复杂因果边,但已能展示“引用了哪些知识、调用了哪些工具”)。
- 反馈系统:记录点赞/点踩,为后续自学习埋下伏笔。
总结v1.0的成果与局限
✅ 成果:透明可验证的基础已经建立——用户能翻阅记忆、调节性格、追溯推理链。 ⚠️ 局限:元认知缺失(无法自我调整)、迎合风险(模型可能顺着用户说)、模块耦合(事件总线未引入)、长期记忆提炼粗糙(会把“我喜欢吃苹果”提炼成“用户对水果有偏好”)。
v2 架构设计:让系统自己“说出”决策过程
v2 的核心思想是 “将决策过程数据化,并让数据流动起来” 。我重构了整个架构,从三个维度分解问题。
横向架构:认知风格作为可插拔策略
记忆记什么、引用怎么强引、解释多深——这些原本分散在代码各处的逻辑,被抽象成 CognitiveStrategy 接口。八种荣格八维风格各自实现该接口,统一控制:
- 输入改写(L1) process_input()
- 记忆过滤(L2)filter_memories()
- 检索权重(L3)adjust_retriveal_weights()
- 工具优先级(L4)prioritize_tools()
- 答案风格(L6)style_answer()
记忆、引用、解释三个子系统与认知策略之间的对应关系
下面展示核心接口和实现片段:
# 认知策略抽象接口
class CognitiveStrategy(ABC):
@abstractmethod
def filter_memories(self, memories: List[MemoryItem]) -> List[MemoryItem]:
"""记忆检索层:对召回的记忆进行过滤/排序"""
pass
# Ti 策略:优先保留因果逻辑的记忆
class TiStrategy(CognitiveStrategy):
def filter_memories(self, memories: List[MemoryItem]) -> List[MemoryItem]:
# 假设记忆的 metadata 中有 "causal" 标记
causal = [m for m in memories if m.metadata.get("causal")]
non_causal = [m for m in memories if not m.metadata.get("causal")]
# 按置信度排序,因果记忆在前
causal.sort(key=lambda m: m.confidence, reverse=True)
non_causal.sort(key=lambda m: m.confidence, reverse=True)
return causal + non_causal
用户调节置信度滑块时,系统自动切换策略实例,实现“横向可插拔”。
横向架构中,我们面临的核心问题是:记忆检索、引用格式、解释深度等行为与“AI 的性格”强耦合,但代码中却分散在不同模块,导致切换一种思维风格需要修改多处逻辑。
例如,Ti(内倾思考)风格希望记忆检索优先保留因果链、引用格式严谨带 ID、解释偏逻辑推导;而 Fe(外倾情感)风格则希望记忆优先召回社交相关内容、引用语气更柔和、解释注重群体价值。v1.0 中这些逻辑散落在 process_stream 的各处 if-else 中,新增一种风格意味着复制粘贴大量代码,极易出错。
解决方案:将“认知风格”抽象为统一接口 CognitiveStrategy,把记忆过滤、检索权重、工具优先级、答案风格等行为全部收归到策略类中。每种风格(Ti/Te/Fi/Fe/Si/Se/Ni/Ne)实现该接口,系统根据用户画像的置信度动态选择策略实例。
设计原因:
- 单一职责:每个策略类只负责一种思维模式,修改 Ti 风格不会影响 Fe 风格。
- 开闭原则:新增一种认知风格(如大五人格)只需新增一个策略类,无需改动主流程。
- 可测试性:可以独立测试每种策略下的记忆过滤、权重调整等行为。
- 用户可调节:置信度滑块直接映射到策略切换,实现了“性格可旋钮”的交互。
综述:通过这种设计让系统的“横向”扩展能力大大增强,也为后续引入元认知动态调整策略奠定了基础。
纵向架构:五层数据流 + 证据图
将一次对话的数据处理拆分为五个层次,每层只做一件事,并自动记录本层的输入、输出、决策依据:
| 层级 | 职责 | 可审计内容 |
|---|---|---|
| L1 输入理解 | 改写查询、意图识别 | 原始输入 → 改写后查询;意图分类结果及依据 |
| L2 记忆检索 | 从短期/长期记忆召回 | 召回了哪几条记忆、相似度分数、过滤逻辑 |
| L3 知识检索 | 从知识库检索文档 | 检索到的片段、混合检索权重、重排序分数 |
| L4 工具调用 | 执行工具、多轮调用 | 工具名、参数、结果、执行顺序 |
| L5 推理生成 | LLM 生成答案 | 选择的认知风格、使用的证据(记忆ID/知识ID) |
| L6 输出解释 | 生成最终解释 | 简洁/逻辑/调试模式、Mermaid 流程图 |
下面展示核心接口和实现片段:
# 证据图构建器核心方法
def add_user_input(self, user_input: str):
"""添加用户输入节点"""
self.user_input = user_input
node = EvidenceNode(type="user_input", content=user_input, metadata={"timestamp": time.time()})
self.graph.add_node(node)
self.user_node_id = node.id
return node
def add_citations(self, citations: List[str]):
"""添加知识库引用节点"""
for doc in citations:
node = EvidenceNode(type="citation", content=doc, metadata={"source": "rag"})
self.graph.add_node(node)
if self.user_node_id:
self.graph.add_edge(self.user_node_id, node.id)
每层产生的“证据”被统一收集到 EvidenceGraph(证据图) 中,最终输出为 Mermaid 流程图,用户可直观看到推理链。
在 v1.0 中,整个对话处理流程是一个巨大的 process_stream 函数:输入改写、记忆检索、知识检索、工具调用、LLM 生成、解释输出全部揉在一起。这不仅导致代码难以维护,更关键的是——用户只能看到最终答案,无法了解 AI 在中间每一步做了哪些决策。当答案出错或令人困惑时,用户无从知道是记忆召回了错误内容,还是检索权重不合理,或是工具调用失败。
纵向架构的核心目标:将黑盒拆解为可审计的流水线。
我们按数据处理顺序将流程拆分为六个独立层次(L1~L6),每个层次只负责一件事,并且强制记录本层的输入、输出、关键决策依据。例如:
- L2 记忆检索不仅要返回记忆列表,还要记录每条记忆的相似度分数和过滤原因(“因为 Ti 模式优先因果记忆,所以过滤掉了非因果条目”)。
- L3 知识检索要记录混合检索的权重(向量 0.6,关键词 0.4)以及重排序后的得分。
这些“审计数据”被统一收集到 EvidenceGraph(证据图) 中。证据图是一个有向图,节点代表记忆、知识片段、工具调用、推理步骤等,边代表引用或因果关系。最终,输出层将证据图渲染为 Mermaid 流程图,用户可以直观地看到“AI 从用户问题出发,经历了哪些步骤,每一步依据了什么,最终得到了答案”。
设计原因:
- 可审计性:每一层的数据都被记录下来,用户可以逐层检查,而不只是相信 AI 的自我解释。
- 问题定位:当系统表现异常时,开发者可以快速定位到具体层(例如证据图中发现 L2 召回了一条不相关的记忆,就能针对性优化记忆检索策略)。
- 可扩展性:新增一层(如“安全过滤层”)只需在流水线中插入,不影响其他层。
- 透明即信任:用户看到完整的推理链后,会更愿意相信 AI 的结论,因为每一步都是可验证的。
综述:通过这张图(数据流图/序列图)展示了用户输入如何依次流经六层,以及每一层的输出如何汇聚到证据图中。这种设计将“透明”从口号变成了可操作、可展示的工程实践。
全局架构:分层解耦 + 横切关注点
对于元认知我思考了很久,偶然间我得知利贝特实验证明了大脑也做不到元认知实时调整,大脑的动作电位甚至可能只是一场欺诈,当然科技依旧在发展,目前这是我能逼近到的工程极限。因此为了管理日益复杂的模块,我将系统划分为六个层次,并引入两个横切组件:
- 交互层:Streamlit 前端
- 应用层:
Orchestrator(对话编排)、ExplanationGenerator(解释生成) - 策略层:
CognitiveStrategy、RouteSelector、EvidenceGraphBuilder - 能力层:
MemoryAccessor、Retriever、ToolExecutor - 存储层:短期记忆(deque)、长期记忆(ChromaDB)、知识库(ChromaDB)
- 横切关注点:
EventBus(事件总线)、MetaCognition(元认知服务)
所有模块通过事件总线解耦:记忆检索、知识检索、工具调用等都会发布事件;元认知订阅事件,分析指标后下发调整指令。整个系统形成了一个 “执行 → 发布事件 → 审计分析 → 动态调整” 的闭环。
数据流程图
数字表示数据流动的顺序(大致时序)。实线表示主要数据流,虚线表示缓存回环。
时序图
模块间的调用顺序和数据传递如上
元认知与事件总线
图注:
-
事件发布(虚线箭头):各业务模块(路由、证据图、记忆、检索、工具、解释、前端)向事件总线发布特定类型的事件。
-
事件总线:作为中枢,将事件推送给元认知服务。
-
元认知内部处理:
Collector:收集事件数据,写入内部指标或反馈日志。Auditor:调用审计函数(如_audit_route,_audit_evidence)生成评分和细节。Analyzer:根据阈值(如证据质量低于60分)检测异常,并判断是否存在用户反馈与审计的矛盾。Adjuster:生成调整指令(如{'layer':'retriever','params':{'threshold':0.8}})。
-
调整指令下发(实线箭头):调整事件经事件总线发送回各业务模块,模块调用
apply_adjustment更新自身参数。 -
自我调整(虚线):元认知也可以发布自我调整事件(如修改分析阈值、调整奖励权重),形成递归优化。
下面展示核心接口和实现片段:
def _is_feedback_conflicting(self, feedback: Dict) -> bool:
if feedback.get('type') == 'like':
recent_exp = [m for m in self.internal_metrics if m['event'] == 'explanation_generated']
if recent_exp and recent_exp[-1]['score'] < 60:
return True
return False
def _report_conflict(self, feedback: Dict):
self.event_bus.publish("conflict_detected", {
"message": "虽然您觉得这个回答有帮助,但它的证据链不完整,我们正在优化。",
"feedback": feedback
})
logger.warning(f"用户反馈与内部审计矛盾: {feedback}")
随着系统功能增加——记忆追溯、RAG检索、工具调用、解释生成、用户画像、证据图——模块间的依赖关系变得越来越复杂。v1.6 时代,Orchestrator 直接依赖所有能力层组件,任何调整(如修改记忆检索参数)都可能影响到主流程。更严重的是,系统缺乏统一的反馈回路:虽然记录了用户反馈,但无法自动分析这些反馈并动态调整行为。元认知的设想一直停留在理念阶段。
全局架构的核心目标:让模块各司其职,并构建一条“可审计、可调整”的反馈闭环。
我们将系统划分为六个清晰的层次:
- 交互层只负责界面展示。
- 应用层(
Orchestrator、ExplanationGenerator)负责对话编排和解释生成,不直接接触存储。 - 策略层(
CognitiveStrategy、RouteSelector、EvidenceGraphBuilder)封装了所有“决策逻辑”,包括认知风格、路由选择、证据图构建。 - 能力层(
MemoryAccessor、Retriever、ToolExecutor)提供具体的数据访问和执行能力。 - 存储层负责持久化。
- 横切关注点(
EventBus、MetaCognition)独立于业务层,负责全局的通信与自优化。
引入 事件总线 是解耦的关键。所有业务模块(记忆检索、知识检索、工具调用、解释生成、甚至前端)都不再直接调用元认知,而是发布事件到总线。元认知服务订阅这些事件,收集审计指标(如证据图质量、解释忠实度、工具成功率),进行分析后,再通过事件总线向各模块下发调整指令(如修改检索权重、切换认知策略、强制引用等)。整个系统形成了 “执行 → 发布事件 → 审计分析 → 动态调整” 的闭环。
设计原因:
- 解耦:
Orchestrator不再需要知道元认知的存在,它只需要在关键点发布事件。任何新的监控或审计组件都可以通过订阅事件接入,而不影响主流程。 - 可扩展性:新增一种审计指标(如“迎合风险检测”)只需在元认知中添加一个订阅处理器,无需修改业务模块。
- 可测试性:可以单独测试事件总线的分发逻辑、元认知的审计函数,以及各模块对调整指令的响应。
- 自我进化:元认知不仅可以调整业务模块,还可以发布自我调整事件(如修改审计阈值、调整分析周期),实现递归优化。这为后续引入强化学习代理(v3方向)奠定了基础。
综述:图中展示了事件总线和元认知如何作为横切关注点与各层交互:虚线箭头是事件发布,实线箭头是调整指令。这种设计让系统从“被动记录”走向“主动审计”,从“固定规则”走向“动态自适应”。它是 v2 版本区别于 v1.x 的最核心特征。
v2的核心设计决策
- 事件总线只记录,不承担控制指令分发:避免成为中心枢纽,保持各层独立。
- 元认知直接调用各模块配置接口:调整指令不经过总线,防止循环依赖。
- 优化目标明确为“不透明=不存在” :所有调整依据证据完整性、引用忠实度、自洽性,拒绝以用户满意度为唯一优化目标。
- 机械解释作为后续扩展:v2聚焦于框架搭建,v3再引入机械解释用于验证解释忠实性。
第三章 v2 的落地与未竟之路
3.1 已实现的关键组件
以下是几个最关键的实现:
- 事件总线与元认知服务(
InMemoryEventBus,AdaptiveMetaCognition) 所有业务模块(路由、证据图、记忆、检索、工具、解释、前端)都向总线发布事件。元认知订阅这些事件,内部实现了Collector(收集指标)、Auditor(调用审计函数生成评分)、Analyzer(阈值检测与冲突判断)、Adjuster(生成调整指令)。目前支持路由多样性审计、证据图质量审计、记忆校验和审计、解释忠实性审计。 - 证据图构建器(
EvidenceGraphBuilder)与 Mermaid 可视化 每一层处理后将决策依据(记忆 ID、知识片段、工具调用结果)写入EvidenceGraph。构建器自动添加节点和边,最终生成 Mermaid 流程图。用户可以在前端折叠面板中查看“推理链图”,直观追溯 AI 的每一步决策。 - 认知策略模式(8 种策略完整实现)
TiStrategy、TeStrategy、FiStrategy、FeStrategy、SiStrategy、SeStrategy、NiStrategy、NeStrategy全部实现CognitiveStrategy接口。每种策略独立控制输入改写、记忆过滤、检索权重、工具优先级、答案风格。用户通过侧边栏滑块实时调整置信度,系统动态切换策略实例。 - 记忆访问器(
MemoryAccessor)统一短期/长期记忆接口 封装了MemoryManager,对外提供search、add、get_recent方法,内部自动融合短期记忆(deque)和长期记忆(ChromaDB)。支持按相似度排序和关键词降级。 - 工具执行器(
ToolExecutor)与缓存 支持多轮工具调用,按策略优先级排序工具执行顺序,并内置内存缓存(可配置最大容量)。工具调用结果自动记录到证据图中,并发布ToolEvent。 - 解释路由与对比功能
ExplanationRouter根据用户画像选择当前认知功能,调用ExplanationGenerator生成自然语言解释和推理链 JSON。前端支持“对比其他解释风格”,用户可以选择不同认知功能生成同一问题的另一种解释,并评分反馈。
3.2 仍待解决的问题
尽管 v2 已经具备了可审计、可调节、可自适应的核心能力,但以下问题仍未完美解决:
- 迎合性:元认知目前只能监控“用户反馈与内部审计矛盾”并发出警告,但尚未实现自动干预。例如,当模型明显顺着用户说时,系统无法主动切换认知策略或调整 prompt 来保持中立。这需要 v3 引入强化学习或更复杂的规则引擎。
- 记忆提炼:短期记忆→长期记忆的提炼策略仍较粗糙。目前只是简单拼接高置信度记忆的前 100 字,经常把“我喜欢吃苹果”提炼成“用户对水果有偏好”。理想的提炼应该利用 LLM 进行语义压缩,并保留时间、情感等关键元数据。
- 多轮工具调用稳定性:在复杂场景下(如“先查天气,再根据温度推荐衣服,然后计算温差”),模型可能只调用一次工具就停止,或者参数提取错误。虽然通过 few-shot 示例有所改善,但仍不够鲁棒。
- 机械解释:当前解释主要依赖 LLM 自生成,没有实现真正的“机械解释”(如注意力热图、特征归因)。解释的忠实性只能通过“引用的证据是否在证据图中”来间接验证,无法回答“模型在生成过程中每个 token 的概率分布”。
- 自学习:v2 的策略调整完全依赖元认知的硬编码规则(如证据质量低于 60 分就提高检索阈值)。没有引入强化学习或在线学习,系统无法从历史交互中自动优化奖励函数和探索策略。
3.3 为什么 v2 选择停在这里
v2 的架构已经完整,核心透明能力(可追溯、可审计、可干预)已具备。剩下的问题(RL、记忆整合、机械解释)属于 v3 范围,需要更长的周期和更多的实验数据。
更重要的是,工程需要适时暂停。一个系统不可能在实验室里无限迭代到完美(其实是我做不完,v3东西太多了,我要开摆)。v2 已经可以在真实场景中使用:用户能够亲手翻阅记忆、调节性格、追溯推理链,元认知能够自动调整检索权重和认知策略。
结语:透明AI是一道慢变量
回顾 v1 到 v2 的历程:从能跑,到能用,到可审计。每一个版本都是一次对“不透明”的对抗。
- v1 让 AI 活在了本地,用户可以翻阅记忆、调节性格、追溯推理链——这是“能跑”。
- v1.5 拆分了模块,引入了证据图雏形,用户可以查看引用了哪条记忆、调用了哪个工具——这是“能用”。
- v2 用事件总线和元认知重构了整个系统,每一层都会自动记录决策依据,元认知可以审计、分析、下发调整指令——这是“可审计”。
透明不是一蹴而就的。它需要不断逼近:把黑盒打开一条缝,然后撬开一扇窗,最后拆掉一面墙。这个过程很慢,没有“一键透明”的魔法,只有一行行代码、一次次调试、一场场深夜的自我怀疑。
这个项目不追求热闹,只追求诚实。它可能不够“像人”,不够流畅,甚至偶尔犯蠢。它只为证明——记忆可以翻开,性格可以拧动,推理链可以画成图。
回到那个赌约。那个消失的 AI 不会再回来了,但它的挑衅让我开始思考:我们到底需要什么样的 AI?我的答案是:一个可以说得出“为什么”的 AI。
v2 停在这里,不是终点,而是起点。剩下的路(迎合性干预、智能记忆提炼、机械解释、强化学习自进化)留给 v3,也留给更多对透明 AI 感兴趣的人,v3 我计划引入强化学习代理,让元认知不再依赖硬编码规则,而是从交互中自动优化策略——当然,这又是一场硬仗。
项目放这儿了:
GitHub仓库:github.com/Doctor-Limi…(欢迎issue,暂不接受PR,毕竟代码还能跑,我怕你一改就崩 备注:我是懒狗,会更新的)
在线演示:http://43.132.194.13:8501/(节点在香港,如果没崩的话 备注:同上)
最后,回到最初那个问题:“我能不能亲手验证AI在想什么?”
如果你也好奇这种可能性,欢迎来 GitHub 逛逛,提个 issue,或者安静地看。毕竟,让 AI 变透明,从来不是一个人的事。
展望 v3:自优化的起点 v2 的元认知还依赖硬编码规则(比如证据质量低于60分就提高检索阈值)。v3 计划引入强化学习代理,让系统从交互中自动学习最优策略——包括调整认知功能权重、检索参数、工具优先级,甚至探索新的解释风格。下图是 v3 的架构设计(在做了在做了,别催了),欢迎有兴趣的朋友一起讨论、贡献想法。