立项背景和目标: 市面上的 AI 对话工具大多是单线程问答,无法跨会话管理任务、也不能在对话中直接触发行动。目标是构建一个本地部署的「对话即操作」AI 助手——用户说一句“帮我记下明天开会”,AI 自动调用工具写入待办;说一句“帮我看看这个网页”,AI 自动抓取并总结,实现真正的 Agent 交互闭环。
核心功能(4大模块): (1)多会话管理:左侧边栏支持创建、切换、删除多个独立对话,首条消息自动生成会话标题,全部历史 SQLite 持久化;(2)DeepSeek Function Calling 工具调用:AI 自主判断何时调用内置工具,包括 add_todo(添加待办)、list_todos(查看待办)、fetch_webpage(网页正文抓取+摘要)、calculate(安全 AST 数学计算),4个工具覆盖主流任务场景;(3)流式对话(SSE):后端 Server-Sent Events 实时推送,打字机效果输出,工具执行结果独立气泡推送,工具完成后 AI 继续流式回复,全链路无阻塞;(4)长对话记忆压缩:对话超过20条消息自动触发压缩,调用 DeepSeek 将旧消息摘要成200字背景,下次对话携带摘要而非全量历史,解决 token 超限问题。
业务流程: 用户发送消息 → FastAPI 接收并存库 → 携带历史+摘要调用 DeepSeek → 判断是否触发 Tool Calling → 执行工具(写待办/抓网页/计算)→ SSE 实时推送前端 → 工具完成后 AI 继续作答 → Vue3 前端 Pinia 状态管理渲染三栏界面(会话栏+对话区+待办面板)。
整体架构: 前后端分离。后端 Python + FastAPI + SQLAlchemy ORM + SQLite(三张表:sessions/messages/todos),核心分层为 routers(API路由)/ core(AI引擎+工具执行)/ database(数据模型);前端 Vue3 + Pinia + Vite,单文件组件 App.vue 实现三栏布局,api层封装所有接口调用,SSE 流通过 ReadableStream 逐行解析。
我的责任模块与量化结果: 独立完成全部代码,共22个文件。核心亮点:(1)Tool Calling 全链路——assistant 消息携带 tool_calls JSON 存库,tool 消息存 tool_call_id 关联,执行完成后重新构建完整消息链再次请求 AI 作最终回复,严格遵守 DeepSeek 函数 calling 消息格式规范;(2)SSE 流解析——前端用 ReadableStream reader 逐块读取,按 分割后解析 前缀 JSON,区分 text/tool_calls/tool_result/done 四种事件类型,动态更新 placeholder 消息;(3)记忆压缩策略——新消息数超阈值(20条)时,取全量消息排除最近10条,单独调用 DeepSeek 生成摘要并追加到 session.summary 字段,压缩后新对话上下文从 O(n) 降至 O(1)+固定摘要长度。\ndata:
难点与解决: (1)Tool Calling 流式模式下 arguments 分片传输:DeepSeek 流式返回时 function arguments 是分多个 chunk 累加的,在前端通过 逐片拼接, 时才触发工具分发,避免 JSON 解析不完整崩溃;(2)工具执行后 AI 需要“继续说话”:工具执行结果存为 role=tool 消息后,重新调用 重构完整消息链(含 tool_calls + tool result),再次发起流式请求让 AI 基于工具结果作答,两段流分别推送前端;(3)安全计算工具:拒绝使用 eval(),改用 Python AST 模块解析表达式树,只允许 Constant/BinOp/UnaryOp 节点和白名单运算符,杜绝代码注入风险。tool_calls_acc[index].arguments +=finish_reason === "tool_calls"_build_messages()