腾讯开源Octop源码拆解:单进程自托管多用户AI助手架构

文章目录

    • 前言
    • [1. 先说说它到底是个啥](#1. 先说说它到底是个啥)
      • [1.1 多用户](#1.1 多用户)
      • [1.2 多智能体](#1.2 多智能体)
      • [1.3 多渠道](#1.3 多渠道)
      • [1.4 自托管](#1.4 自托管)
    • [2. 四条藏在代码里的设计主线](#2. 四条藏在代码里的设计主线)
      • [2.1 主线一:单进程,不搞外部队列](#2.1 主线一:单进程,不搞外部队列)
      • [2.2 主线二:双数据库,谁都别嫌谁](#2.2 主线二:双数据库,谁都别嫌谁)
      • [2.3 主线三:依赖只许向内流,不许往外拐](#2.3 主线三:依赖只许向内流,不许往外拐)
      • [2.4 主线四:一张库,一个进程,一次重启](#2.4 主线四:一张库,一个进程,一次重启)
    • [3. 运行时全景](#3. 运行时全景)
    • [4. 一句话从 Web 到大脑,到底走了多远](#4. 一句话从 Web 到大脑,到底走了多远)
    • [5. 黑话翻译表](#5. 黑话翻译表)
    • [6. 技术装备清单](#6. 技术装备清单)
    • [7. 你该从哪开始读](#7. 你该从哪开始读)
      • [7.1 想看架构设计的](#7.1 想看架构设计的)
      • [7.2 想搞集成和二次开发的](#7.2 想搞集成和二次开发的)
      • [7.3 关心存储和运维的](#7.3 关心存储和运维的)
      • [7.4 只关心安全的](#7.4 只关心安全的)

P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 传送门http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。

前言

最近翻到一个挺有意思的东西,腾讯开源的,叫 Octop。

说是 AI 助手平台,其实就是一个 Python 包,pip 装完就能跑。

我第一次看到的时候还以为又是那种"装完要配五个环境变量、启动三个容器、最后跑不起来"的玩具。

结果跑起来一看------人家就一个进程,一个端口,数据全在你自己电脑的 ~/.octop/ 里。

行吧,那今天就带大家把这玩意儿的骨架扒一扒。这篇不写具体代码,先画个地图,省得你们跟我上次一样,一头扎进去三天没找着北。

1. 先说说它到底是个啥

一句话:自托管的多用户 AI 助手平台。

注意几个关键词,少一个味道就不对了。

1.1 多用户

不是那种"全家共用一个账号"的多用户,是真·多个用户,JWT 隔离,每个人有自己的会话、自己的专家,但是知识库可以共享。

怎么理解呢?就像公司茶水间------杯子是各人的,但茶叶是公共的。

1.2 多智能体

一个用户可以养好几个 Agent,行话叫"专家"。

不光能各干各的,还能组队,叫 AgentTeams。

你可以理解为:你手下有一个产品、一个前端、一个后端,它们自己开小会,不用你传话。

说到这个我就来气,我以前带团队的时候,产品和后端吵起来还得我居中传话。

人家 Octop 倒好,Agent 之间直接发消息,连我这个"项目经理"都省了。

1.3 多渠道

Web、命令行、飞书、钉钉、QQ、微信、Telegram、Discord、企业微信,再加一个定时任务。

你没看错,九个入口。

一般项目做一个 Web 界面就敢叫"全渠道触达"了,人家是真的把能发消息的地方全接了一遍。

1.4 自托管

划重点------除了要调大模型的 API,其他什么都不用装。

没有 Redis,没有 RabbitMQ,没有 Celery worker,没有那一堆"为了高可用"但你根本用不上的东西。

一个进程,一个端口,完事。

我上次给一个朋友介绍微服务架构,讲了两个小时,他最后问我:"那我本地怎么跑?"

我说:"先起 Redis,再起 MySQL,再起 Nacos,再起网关,再起订单服务,再起用户服务......"

他沉默了一会儿,说:"那我还是用 Excel 吧。"

Octop 就是那种"让你朋友不用回去用 Excel"的架构。

2. 四条藏在代码里的设计主线

读源码最怕什么?

最怕每个文件都写得挺漂亮,但你不知道它们为什么要这么写。

Octop 这边有四条主线,你抓住了,后面看什么都顺。

2.1 主线一:单进程,不搞外部队列

没有 Redis,没有 Celery,没有独立 worker。

所有乱七八糟的入口,都通过一个叫 HarnessProcessor 的东西在进程内汇流。

代价是什么?所有阻塞调用都得塞进 run_in_executor,不然事件循环就被你卡死了。

但好处也实打实------没有跨进程一致性问题,进程里的状态,理论上全可以从数据库重建出来。

这就像你把所有文档都存在一个文件夹里,每天下班拷一份到移动硬盘。

哪怕电脑炸了,换一台新的,把硬盘一插,什么都不耽误。

2.2 主线二:双数据库,谁都别嫌谁

控制面默认跑 SQLite(开了 WAL),也能切 PostgreSQL(用 psycopg3 连接池)。

同一套 Repo 代码,靠在边界把 ? 重写成 %s,再加一个 _CompatRow,把方言差异抹平了。

就像你做了一道菜,湖南人来了多放辣椒,广东人来了少放辣椒,但菜本身是同一盘。

存储还被明确分成三层:Octop 控制面、harness checkpoint、agent memory。

三层各过各的,不许混。

我以前见过一个项目,用户表、日志表、缓存、临时队列全塞在一个库里,最后一张表两千万行,查个列表要三秒。

后来 DBA 去他们公司楼下堵了他们三天。

2.3 主线三:依赖只许向内流,不许往外拐

复制代码
dashboard/ ──HTTP──► api/ ──► infra/ ──► infra/utils/, octop.config
cli/ ──► launch.py ──► api/ + infra/

规矩是这样的:

  • infra/ 不许 import api/、cli/、launch.py;
  • api/ 不许 import cli/;
  • infra/db/repos/ 只准依赖 _base 和 utils。

这些不是建议,是 AGENTS.md 里写死的禁令。

唯一的例外是 launch.py,它能同时看到 infra.server 和 api.app------因为它就是那个把所有人串起来的启动入口。

我就想问一句,有多少项目的 import 是这种画风:

复制代码
// 底层工具类 import 了顶层业务服务
// 业务服务又 import 了底层工具类
// 最后谁也离不开谁,重构?重构就是重写。

Octop 这套规矩,说白了就是一句话------底层不许知道上层是谁。

就像厨师不需要知道谁点的菜,他只负责做。

2.4 主线四:一张库,一个进程,一次重启

OctopServer.start() 每次都是按依赖顺序,把整棵运行时树重建一遍。

进程里没有那种"关不掉、清不掉、不知道什么时候被塞进来"的隐性状态。

所以它才能搞 replace_services(),把所有单例热重绑到新库上------

因为状态本来就是从库里来的,换个库就等于换了个存档点。

这让我想起我以前维护的一个系统,里面有个全局缓存,初始化的时候从数据库读了一波,之后就再也不刷新了。

每次改完配置,运维小哥都得在群里发一句"重启一下哦",然后盯着屏幕等三分钟。

Octop 这种设计,就相当于告诉你:别在内存里偷偷藏东西,有事儿就去查库。

虽然慢一点,但你睡得着觉。

3. 运行时全景

来,看全家福。

复制代码
OctopServer
├─ DatabasePool   SQLite (WAL) 或 PostgreSQL (psycopg 池)
├─ SharedServices   DI 根:paths + config + RepoBundle
├─ ExpertCatalog    启动时扫描 agents/experts/library/
├─ UserManager
│   └─ AgentManager(全局注册表,一个进程一个)
│       └─ HarnessAgentRuntime(每个 agent 一个)
├─ HarnessAgent    智能体运行时(octop-harness / LangGraph)
├─ GlobalProcessor  IM / Web / CLI / Cron 统一入口
├─ ChannelManager   IM 连接(octop-gateway)
├─ BackendWorkspace  可插拔文件 I/O
├─ Gateway(ChannelManager + WebSocketHub + Cron 触发器)
├─ CronManager(进程级 APScheduler)
├─ TrajectoryService(轨迹投影 + 实时总线)
└─ FastAPI app(uvicorn)

怎么看这棵树?

最上面是数据库,最下面是 FastAPI。

中间一坨,全是干活的。

UserManager 管用户,AgentManager 管所有 Agent 的注册表------一个进程就一个。

每个 Agent 运行的时候有自己的 HarnessAgentRuntime,相当于每个专家有自己的工位。

GlobalProcessor 是所有消息的总入口,不管你是从 Web 发的、从飞书发的、还是定时任务触发的,最后都汇到它这儿。

CronManager 用的是 APScheduler,进程内调度。

TrajectoryService 负责把每次对话的轨迹投影成事件,一边落库一边实时推给前端。

我第一次看这张图的时候,第一反应是:这模块分的,比我衣柜还整齐。

我衣柜是什么样呢------外套和内裤挂在同一根杆上,找袜子得翻三个抽屉。

Octop 这个模块划分,简直就是程序员版的"断舍离"。

4. 一句话从 Web 到大脑,到底走了多远

来,我们把一次对话拆成玻璃盒,一步一步看。

假设你在网页上发了一句话。

复制代码
用户输入
│
WebSocket /api/agents/{aid}/chat/ws     ← 前端那层
▼
api/routers/chat/ws.py → gateway/ws/ws_channel.py
│  组装 InboundMessage,解析 session_key
▼
GlobalProcessor.iter_turn_chunks(msg)
│  ① 解析用户/locale/session_key
│  ② 处理 slash 命令
│  ③ HITL 分支(需要人确认的那种)
│  ④ 构造 harness request
│  ⑤ 订阅轨迹
▼
AgentManager.stream() → HarnessAgent
│  LangGraph 执行,逐 chunk 产出
▼
TrajectoryService.observe_chunk()
│  投影成 assistant / tool / user 事件
│  聚合 token,落库 + 实时发布
▼
WebSocketHub.push_to_thread() → 浏览器渲染

看出门道没有?

从你按下回车,到浏览器打出第一个字,中间过了五个大节点。

最妙的是------如果你换成从飞书发这句话,ws_channel 换成对应的 ChannelManager,iter_turn_chunks 换成 __call__ → project_stream → MessageEvent,下游一模一样。

这就是"统一管线"的意义。

我见过太多项目,Web 一套接口、App 一套接口、小程序一套接口,三套接口背后是三套逻辑,最后改一个 bug 要改三个地方。

测试同学每天的工作就是:这三个端的表现怎么又不一样了?

Octop 这个设计,相当于不管你从哪个门进来,进了大厅之后走的是同一条走廊。

5. 黑话翻译表

读源码最怕一堆术语堆脸上,跟天书似的。

我给你们翻译一下。

术语 人话 主要源码
surface 消息入口:Web / CLI / IM / Cron infra/gateway/*
turn 一次用户→助手的完整往返 history/trajectory/*
session_key 全局会话寻址键,格式是 agent:channel:subject:chat_type gateway/threads.py:31
thread session_key 绑定的具体会话线程,带历史元数据 gateway/threads.py
chunk harness 吐出来的流式事件,可能是 token、可能是工具调用 gateway/process/stream_project.py
trajectory chunk 投影出来的、能存能回放的事件流 history/trajectory/*
TaskRouter / Processor 就是 GlobalProcessor,把消息路由到正确的 Agent gateway/process/processor.py:135
expert 面向用户的 Agent,一个 Agent = 一个专家 infra/agents/*
workspace Agent 的文件空间,后端可以插拔 infra/backend/*

特别说一下 session_key。

这玩意儿格式是 agent:channel:subject:chat_type,四个字段用冒号拼起来。

什么意思呢?

就是"哪个专家、从哪个渠道来的、哪个用户、在哪个会话类型里"------四个信息一拼,全局唯一。

我第一次见到这种设计的时候,心里想的是:这不就是把所有维度拼在一个字符串里当主键吗?

但仔细一想,确实好用。

你想找某个人在某个群里跟某个 Agent 的所有对话,直接按 session_key 一查,完事。

不用 join 三张表。

当然代价就是------如果你哪天想加第五个维度,这个 key 的格式就得变,所有存过的历史都得兼容。

这就像你家钥匙,一开始只有一把,开所有门。

等你加了门禁卡、指纹锁、人脸识别,回头看那把钥匙,它已经不代表什么了。

6. 技术装备清单

层 技术
语言 Python 3.12+(asyncio,只有真要阻塞的时候才 run_in_executor)
Web FastAPI + uvicorn;Scalar 文档在 /api/docs(默认关)
Agent 运行时 octop-harness(基于 LangGraph)
渠道桥接 octop-gateway
记忆 octop-memory(分层召回 + FTS)
浏览器 octop-browser(CDP + 持久 profile)
控制面 DB SQLite(WAL,默认)或 PostgreSQL(psycopg3)
前端 React 18 + TypeScript + Vite + Ant Design
调度 APScheduler(AsyncIOScheduler)
包管理 uv(uv run pytest,禁止裸 pytest)
质量门 hatchling · ruff · mypy --strict · pytest(跨 Linux/Windows)

注意几个细节。

Python 3.12+,mypy --strict。

做过 Python 项目的都知道,mypy --strict 是什么概念------

就是你写的每一个函数,参数类型、返回值类型,全都得标清楚,漏一个就给你报错。

很多团队的 mypy 是什么画风?

开了,但 --ignore-missing-imports、--no-strict-optional、--ignore-without-code,能关的全关了。

最后 mypy 跑一下,0 errors,皆大欢喜------其实是啥也没查。

Octop 是真·strict。

这说明什么?说明作者对类型系统是有信仰的。

还有一个,包管理用 uv,而且明令禁止裸 pytest,必须 uv run pytest。

这个细节我特别喜欢。

因为很多 Python 项目的"在我电脑上能跑",本质上是因为你用的是那个虚拟环境的 Python,但你切个终端,用全局 Python 跑,依赖全错。

Octop 直接把这条规则写死------不许用全局的,必须走 uv。

就像餐厅规定:所有菜必须从后厨出,不许服务员自己带食材进来。

7. 你该从哪开始读

最后说一下阅读路径。

不同的人,关心的东西不一样。

7.1 想看架构设计的

按这个顺序:01(组合根)→ 02(运行时)→ 03(管线)→ 04(投影)→ 05(历史)。

这是正序,从怎么组装的,到怎么跑的,到消息怎么流的,到轨迹怎么存的。

7.2 想搞集成和二次开发的

03(管线)→ 10(连接器 / MCP)→ 11(前端)。

你就关心一件事:我怎么把自己的东西接进来。

那从管线看起,看 MCP 怎么接,再看前端怎么调,差不多了。

7.3 关心存储和运维的

06(双库)→ 08(工作区后端)→ 12(定时)。

这三个看完,你就知道数据放哪了、文件怎么存的、定时任务怎么跑的。

7.4 只关心安全的

09,单读。

安全这东西,跟别的模块耦合不多,单独拎出来看就行。

行了,地图就画到这儿。

准备好了,就从下一篇开始,咱们聊聊"单进程架构"这个选择背后,到底是怎么权衡的。

P.S. 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 传送门http://blog.csdn.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,否则看看零散的博文就够了。

相关推荐
星核0penstarry42 分钟前
宕机那天 API 还能用,所以模型是假的?
运维·服务器·人工智能·大模型·ai编程·模型指纹
几何心凉1 小时前
端到端具身交互智能正式上线:让 AI 通过屏幕和机器人,真正走进现实世界
前端·人工智能·实时互动·机器人·交互
JAVA_AI人工智能项目实战1 小时前
强化学习与大模型对齐_学习笔记
人工智能·语言模型·自然语言处理
SEO_juper1 小时前
AI 爬虫 robots.txt 检查工具:你的站是不是把 AI 挡在门外了
开发语言·人工智能·爬虫·python·外贸独立站
涛思数据(TDengine)1 小时前
TDengine TSDB 3.4.3.3 上线:流计算分层闭环、虚拟表跨层引用,查询关联一次写完
数据库·人工智能·数据分析·时序数据库·tdengine·工业
碧海银沙音频科技研究院1 小时前
基于ATS308X的无线语音交互对话功能实现
人工智能·嵌入式硬件·深度学习·算法
博.闻广见1 小时前
第10篇:Agent系统的性能优化 —— 缓存、压缩与动态模型路由
java·人工智能·后端·spring·agent
海雅达手持终端PDA1 小时前
配电台区杆塔巡检老卡死?海雅达Model 4/HDT500实测
人工智能·物联网·集成测试·能源·政务
叶子丶苏1 小时前
提示词工程格式四段式与少样本-VibeCoding入门笔记06
人工智能·笔记