从PySide6到Rich+FastAPI:如意Agent终端版架构重构全记录
我是张大鹏做了十多年人工智能带过不少项目。说实话最难的不是把功能做出来是在需求变化时让架构跟得上。最近如意Agent经历了一次彻底的架构转型——从桌面GUI全面转向终端版采用前后端分离架构。本文记录这次重构的完整思路和实现细节。一、为什么要推倒重来如意Agent最初是基于PySide6的桌面应用。PySide6确实好用信号槽机制成熟QSS样式灵活我们甚至做了8套主题皮肤。但跑了几个月后问题逐渐暴露问题具体表现影响打包体积PyInstaller Qt 依赖单文件 180MB分发困难更新成本高跨平台Windows/Mac/Linux 表现不一致维护三套UI代码远程使用必须在本地运行无法远程调用服务器场景完全不可用测试成本GUI自动化测试脆弱CI/CD 难集成每次发版手工验证资源占用运行时内存 200MB低配机器卡顿明显最致命的是部署场景。有用户想在服务器上跑如意Agent作为后台服务但桌面GUI在 headless 环境下直接报错。我们不得不告诉他们“先装个桌面环境。”这显然不合理。二、新架构的核心思路重构目标很明确让Agent回归服务本质UI只是多种消费方式之一。新架构采用“共享后端 多端前端”模式┌─────────────────┐ HTTP/WebSocket ┌─────────────────┐ │ ruyi-cli │ ◄──────────────────────► │ ruyi-server │ │ (Rich终端UI) │ │ (FastAPI服务) │ └─────────────────┘ └────────┬────────┘ │ ┌────────────────────────────┼────┐ │ │ │ ┌─────┴─────┐ ┌──────┴───┐ │ │ Web │ │ Mobile │ │ │ (Vue3) │ │ (未来) │ │ └───────────┘ └──────────┘ │ │ ┌─────────────┴─────┐ │ Core Agent │ │ (agentmain.py) │ └───────────────────┘技术选型层级技术选型理由后端服务FastAPI Uvicorn异步支持好自动API文档WebSocket原生支持终端UIRich TyperPython终端渲染天花板比很多GUI还好看配置管理YAML人机双友好注释支持层级清晰进程通信HTTP WebSocket松耦合支持远程调试方便三、后端服务层实现后端是独立进程负责承载核心Agent和对外提供API。3.1 FastAPI应用入口ruyi-server/src/server/app.pyfromfastapiimportFastAPIfromfastapi.middleware.corsimportCORSMiddlewareimportuvicornimportthreadingfromserver.configimportload_server_configfromserver.routesimportchat,system,llmfromagentmainimportGeneraticAgentfromstorage.chatimportmake_chat_repo# 加载配置configload_server_config()# 创建FastAPI应用appFastAPI(title如意Agent API,version0.1.5,description如意Agent 后端服务 API)# CORS配置支持跨域调用app.add_middleware(CORSMiddleware,allow_originsconfig[cors][allow_origins],allow_credentialsTrue,allow_methods[*],allow_headers[*],)# 全局状态管理classAppState:def__init__(self):self.agent:GeneraticAgent|NoneNoneself.chat_repoNoneself.active_tasks:dict{}app.state.app_stateAppState()# 注册路由app.include_router(chat.router)app.include_router(system.router)app.include_router(llm.router)app.on_event(startup)asyncdefstartup_event():应用启动时初始化AgentagentGeneraticAgent()chat_repomake_chat_repo()agent.set_chat_persistence(chat_repo)# 后台线程运行Agentthreading.Thread(targetagent.run,daemonTrue).start()app.state.app_state.agentagent app.state.app_state.chat_repochat_repoprint(f[Server] Agent 初始化完成当前模型:{agent.get_llm_name()})关键点Agent运行在后台线程主线程处理HTTP请求互不阻塞全局状态通过app.state共享避免全局变量污染CORS全开放方便前端开发和跨域调用3.2 配置分离服务端配置独立为config/server.yamlserver:host:0.0.0.0port:8000workers:1cors:allow_origins:[*]allow_credentials:trueallow_methods:[*]allow_headers:[*]llm:default_provider:kimifallback_providers:[openai,deepseek]storage:chat_db_path:data/chat.dblog_level:INFO配置加载用标准YAML解析约30行代码importyamlfrompathlibimportPathdefload_server_config(config_path:str|NoneNone)-dict:ifconfig_pathisNone:config_pathconfig/server.yamlwithopen(Path(config_path),r,encodingutf-8)asf:returnyaml.safe_load(f)3.3 Chat路由设计聊天是核心功能支持两种模式同步模式REST APIrouter.post(/send)asyncdefsend_message(request:SendMessageRequest)-dict[str,str]:stateapp.state.app_stateifstate.agentisNone:raiseHTTPException(status_code503,detailAgent未初始化)conv_idrequest.conversation_idorstr(uuid.uuid4())task_idstr(uuid.uuid4())# 异步处理任务asyncdefprocess_task()-None:display_queuestate.agent.put_task(request.message,sourceapi)whileTrue:try:chunkdisplay_queue.get(timeout0.1)ifchunkisNone:break# 收集响应片段state.active_tasks[task_id][chunks].append(str(chunk))exceptqueue.Empty:ifnotstate.agent.is_running:breakawaitasyncio.sleep(0.05)asyncio.create_task(process_task())return{task_id:task_id,conversation_id:conv_id}流式模式WebSocketrouter.websocket(/ws/{task_id})asyncdefwebsocket_endpoint(websocket:WebSocket,task_id:str):awaitwebsocket.accept()stateapp.state.app_statetry:whileTrue:iftask_idinstate.active_tasks:taskstate.active_tasks[task_id]# 发送已收集的chunkschunkstask[chunks]forchunkinchunks:awaitwebsocket.send_text(chunk)iftask[status]completed:awaitwebsocket.send_text([DONE])breakawaitasyncio.sleep(0.1)exceptWebSocketDisconnect:print(f[WebSocket] 客户端断开:{task_id})WebSocket的设计很务实Agent内部用Queue生产数据WebSocket循环消费并推送给客户端。不追求零延迟保证不丢消息、不乱序。四、终端客户端实现终端版不是简陋的print而是基于Rich的现代化TUI。4.1 为什么选RichRich的能力远超预期Markdown渲染代码高亮、表格、引用块全部原生支持Panel布局消息气泡、系统提示用Panel轻松实现Spinner/ProgressAgent思考时显示动画体验接近GUI颜色主题256色支持暗色主题下的显示效果非常舒服4.2 三段式流式显示这是终端版最核心的UX创新。Agent的响应分为三个阶段# thinking 阶段 正在分析问题...# summary 阶段 关键结论建议采用方案B因为...# answer 阶段详细解释...代码示例...Rich的Live组件让流式更新很流畅fromrich.liveimportLivefromrich.panelimportPanelfromrich.markdownimportMarkdownwithLive(consoleconsole,refresh_per_second10)aslive:forchunkinstream_response():ifchunk[type]thinking:contentf{chunk[content]}elifchunk[type]summary:contentf{chunk[content]}else:contentchunk[content]live.update(Panel(Markdown(content),title如意Agent))4.3 CLI命令结构用Typer构建命令行入口importtyperfromrich.consoleimportConsole apptyper.Typer(help如意Agent 终端客户端)consoleConsole()app.command()defchat(server:strtyper.Option(http://localhost:8000,--server,-s),model:strtyper.Option(None,--model,-m)):启动交互式聊天会话clientRuyiClient(base_urlserver)sessionChatSession(client,modelmodel)session.run()app.command()defstatus(server:strtyper.Option(http://localhost:8000,--server,-s)):查看Agent运行状态clientRuyiClient(base_urlserver)infoclient.get_status()console.print(f模型:{info[model]})console.print(f状态:{info[status]})if__name____main__:app()五、重构过程中的关键决策5.1 为什么不是TUI框架TextualTextual确实更强大但我们评估后放弃维度RichTextual学习成本低熟悉print即可上手高需要理解组件树、事件循环调试难度低print可辅助调试高屏幕刷新会覆盖print灵活性高自由控制输出中受框架约束包体积小核心仅依赖大额外依赖Rich的增强版print哲学更符合我们的需求渐进增强随时可回退到基础模式。5.2 进程间通信为什么不用gRPCgRPC性能更好但HTTP/JSON在调试和开发体验上碾压curl直接测试API浏览器打开http://localhost:8000/docs看Swagger文档错误信息JSON可直接阅读对于AI Agent场景开发效率 极致性能。瓶颈在LLM API调用不在内部通信。5.3 保留的核心资产重构不是重写核心层完全保留agentmain.py—— Agent主逻辑llmcore.py—— LLM路由与调用agent_loop.py—— 执行循环storage/—— 持久化层刚做完chat.db迁移logstack/—— 结构化日志memory/—— 记忆系统删除的只有UI层src/desktop/、src/pet/、src/frontends/。六、重构收益指标重构前桌面版重构后终端版变化打包体积180MB15MB-92%启动时间3-5秒1秒-80%内存占用200MB40MB-80%CI/CD集成困难原生支持质变远程部署不支持开箱即用质变跨平台需分别测试Python标准库质变最意外的收获是测试覆盖率。终端版可以全量跑E2E测试桌面版只能测核心逻辑。重构后测试从 600 提升到785 passed0 skipped。总结维度内容核心思路共享后端 多端前端Agent回归服务本质关键技术FastAPI后端、RichTyper终端、YAML配置关键决策HTTP/JSON优于gRPCRich优于Textual保留核心层注意事项终端版适合服务器/开发场景桌面版可基于Web技术重建这次重构验证了一个原则架构要服务于场景不要服务于技术栈本身。PySide6不是不好是不适合如意Agent当前的发展阶段。当用户从本地尝鲜转向生产部署时轻量、可远程、可集成的架构才是正解。参考资料FastAPI官方文档Rich文档Typer文档如意Agent终端版实施计划docs/superpowers/plans/2026-05-06-terminal-version.md作者张大鹏日期2026-05-06团队大鹏AI教育GitHub项目地址含完整源码相关推荐如意Agent六边形架构改造从单体巨石到端口适配器如意Agent对话持久化与滚动记忆引擎设计
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2590372.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!