1. 为什么我劝你先别急着养龙虾,用 Hermes 跑通 Scanpy 更实在
最近生物信息学圈子里聊得最多的两个名字,一个是 OpenClaw(大家戏称"龙虾"),另一个是 Hermes(被叫成"爱马仕")。很多人还没搞明白龙虾怎么养,马就已经跑到跟前了。我自己的判断是:如果你现在的核心诉求是用 Python 把单细胞转录组流程跑通,那先养马更划算,因为 Hermes 在代码生成、流程编排、错误自修复上的表现,对生信这种"步骤多、报错碎、依赖烦"的场景特别友好。
这篇文章要解决的就是一个很具体的问题:怎么用 TaoToken 统一 Key,把 Hermes 接到 Scanpy 单细胞分析流程里,从环境准备一路跑到 PBMC 聚类出图。适合谁看?三类人:一是刚接触单细胞、被 Seurat 和 Scanpy 双份文档劝退的;二是手上有一堆.h5ad文件但每次跑流程都要重配环境的;三是想用 AI Agent 辅助生信分析、但不想每个模型都单独申请 Key 的。
Scanpy 是 Python 生态里做单细胞分析的主力工具,能完成 QC、归一化、高变基因、PCA、UMAP、Leiden 聚类、marker 基因检测、细胞类型注释这一整套标准流程。Hermes 则是一个能调用大模型、能执行终端命令、能自动把分析过程沉淀成 skill 的智能体。两者结合,你得到的不是"AI 帮你写代码",而是"AI 帮你把流程跑完并把踩过的坑记下来"。
我实测下来,整个链路里最容易卡住的不是 Scanpy 本身,而是模型接入这一环——不同厂商的 Base URL、Key 格式、模型 ID 都不一样,Hermes 配置里填错一个字符就静默失败。所以下面我会把 TaoToken 作为统一 API 通道的配置写清楚,让你一次配好,后面换模型只改一个 Model ID。
2. TaoToken 前置准备:统一 Key 与 API 通道怎么接
在动手装 Hermes 之前,先把"模型通道"这件事解决掉。Hermes 本身只是个壳,它干活要靠背后的大模型。如果你每个模型都去单独注册、单独拿 Key、单独记 Base URL,配置会非常乱。TaoToken 的作用就是把这些收敛成一个入口:一个 Key、一个 Base URL,模型通过 Model ID 切换。
先明确三个核心参数,后面所有配置都围绕它们:
| 参数 | 值 | 说明 |
|---|---|---|
| Base URL | https://taotoken.net/api | 统一 API 通道地址,注意不要加多余路径 |
| API Key | 在控制台创建 | 形如sk-开头的一串字符 |
| Model ID | 按需选择 | 例如编码/Agent 场景选对应模型标识 |
获取 Key 的路径是:登录官网后进入控制台,在 API Keys 页面创建一个新 Key。建议给这个 Key 起个能认出来的名字,比如hermes-bioinfo,方便以后区分是给哪个 Agent 用的。创建完立刻复制保存,页面刷新后就看不全了。
注意:Base URL 填
https://taotoken.net/api即可,不要自己拼/v1/chat/completions这类后缀,客户端会自动补全。多写一段路径是 404 的高频原因。
如果你后面要长期跑编码类、Agent 类任务,可以顺带了解一下 Coding Plan,它更适合高频调用场景;只是偶尔验证模型通不通,用模型对话页面直接试就行。接入细节和参数说明都在接入文档里,遇到不确定的字段先去那里对一遍,比在终端里瞎试快得多。
这里要强调一个观念:统一 Key 不是省事,而是让排障变简单。当 Hermes 报错时,你只需要判断"是 Key 问题、Base URL 问题,还是 Model ID 问题",而不是在四五个厂商的配置之间来回横跳。生信流程本来就够复杂了,接入层越简单越好。
3. 可复制配置:Hermes 接入 TaoToken 与 Scanpy 环境搭建
这一节是全文的核心,所有片段都可以直接复制。先装 Hermes,再配模型,最后装 Scanpy 依赖。
Hermes 的安装命令(Linux 环境,确保系统有 Python 3.11):
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash装完运行初始化:
hermes setup选择 Quick setup,然后在"设置大模型提供商"这一步,不要选具体厂商,而是走自定义/兼容 OpenAI 协议的入口,填入 TaoToken 的三个参数。对应的配置文件通常落在~/.hermes/下,形如config.toml或settings.json。以 TOML 为例,你需要保证结构是这样:
[model] provider = "openai-compatible" base_url = "https://taotoken.net/api" api_key = "sk-你的Key" model_id = "你的ModelID" [agent] name = "hermes" workdir = "/home/你的用户名/.hermes/hermes-agent"如果你用的是 JSON 形式的 settings 文件,等价写法:
{ "model": { "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的Key", "modelId": "你的ModelID" }, "agent": { "name": "hermes", "workdir": "/home/你的用户名/.hermes/hermes-agent" } }Base URL、Key、Model ID 这三件套必须同时正确,缺一个都会失败。我见过最常见的错误是只改了 Key 没改 Base URL,结果请求打到了默认厂商那边,报 401 却以为是 Key 过期。
接下来装 Scanpy 环境。建议用独立虚拟环境,避免和系统 Python 打架:
python3.11 -m venv ~/scenv source ~/scenv/bin/activate pip install --upgrade pip pip install scanpy leidenalg matplotlib celltypistleidenalg是 Leiden 聚类必需,celltypist用于自动细胞类型注释,matplotlib负责出图。装完后验证:
python -c "import scanpy as sc; print(sc.__version__)"能打印版本号就说明环境 OK。如果 Hermes 要常驻服务器,还需要给它系统服务权限。普通账号直接装服务会报权限错误,用下面这组命令解决:
sudo loginctl enable-linger 你的用户名 su - 你的用户名 cd ~/.hermes/hermes-agent hermes gateway install这样重启服务器后 Hermes 也会自动起来,不用每次手动拉。
4. 验证请求:跑通 PBMC 聚类并检查结果
配置好之后,先做一次最小验证,确认模型通道是通的。在 Hermes 对话里发一句简单的分析请求,比如"帮我用 Scanpy 跑一个 PBMC3k 的聚类流程"。如果它能开始输出代码和步骤,说明 Key 和 Base URL 都对了。
然后进入真正的流程验证。下面这段是精简版 PBMC 流程,可以直接存成pbmc_check.py:
import scanpy as sc import matplotlib.pyplot as plt import warnings warnings.filterwarnings('ignore') sc.settings.verbosity = 2 sc.settings.set_figure_params(dpi=100, facecolor='white') # Step 1: 加载数据 adata = sc.datasets.pbmc3k() print(f"原始维度: {adata.shape[0]} cells x {adata.shape[1]} genes") # Step 2: QC adata.var['mt'] = adata.var_names.str.startswith('MT-') sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True) sc.pp.filter_cells(adata, min_genes=200) sc.pp.filter_cells(adata, max_genes=2500) adata = adata[adata.obs.pct_counts_mt < 5, :].copy() sc.pp.filter_genes(adata, min_cells=3) print(f"QC后: {adata.n_obs} cells, {adata.n_vars} genes") # Step 3: 归一化 adata.raw = adata.copy() sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) # Step 4: 高变基因 sc.pp.highly_variable_genes(adata, n_top_genes=2000) adata = adata[:, adata.var.highly_variable].copy() # Step 5: 降维聚类 sc.pp.scale(adata, max_value=10) sc.tl.pca(adata, svd_solver='arpack', n_comps=50) sc.pp.neighbors(adata, n_pcs=15, n_neighbors=15) sc.tl.umap(adata, min_dist=0.3) sc.tl.leiden(adata, resolution=1.0) # Step 6: Marker 基因 sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon', use_raw=True) names = adata.uns['rank_genes_groups']['names'] n_clusters = len(names.dtype.names) print(f"聚类数: {n_clusters}") for ci in range(n_clusters): top = [str(names[j][ci]) for j in range(3)] print(f" Cluster {names.dtype.names[ci]}: {', '.join(top)}") # Step 7: 出图 sc.pl.umap(adata, color='leiden', legend_loc='right margin', show=False) plt.savefig('umap_clusters.png', dpi=150, bbox_inches='tight') print("UMAP 已保存到 umap_clusters.png")运行:
stdbuf -oL -eL python3 -u pbmc_check.pystdbuf和-u是为了让输出实时刷新,长流程里不加这个你会以为程序卡死了,其实只是在缓冲。
成功的结果长这样:QC 后细胞数大约在 2600 到 2700 之间,聚类数在 resolution=1.0 时通常是 8 到 10 个,每个 cluster 能打印出 top3 marker 基因,最后生成一张 UMAP 图。如果这些数字和文件都出现了,说明整条链路——TaoToken 通道、Hermes、Scanpy——全部跑通。
想进一步做自动注释,可以加 CellTypist:
from celltypist import models import celltypist adata_ct = adata.raw.to_adata() adata_ct.obs = adata.obs.copy() sc.pp.normalize_total(adata_ct, target_sum=1e4) sc.pp.log1p(adata_ct) predictions = celltypist.annotate( adata_ct, model='Immune_All_Low.pkl', majority_voting=True, over_clustering='leiden' ) adata.obs['celltypist_label'] = predictions.predicted_labels['majority_voting'].values print(adata.obs['celltypist_label'].value_counts())模型首次使用会自动下载。跑完你能看到每个 cluster 被标注成 CD4+ T、CD8+ T、NK、B cell、Monocyte 等具体类型。
5. 本篇常见报错排查:401、local proxy failed、reading choices 与 OAuth
这一节按真实报错来对,遇到问题直接查表。
401 Unauthorized:九成是 Key 或 Base URL 的问题。先确认 Key 没有多余空格,再确认 Base URL 是https://taotoken.net/api而不是别的。如果 Key 是从网页复制的,注意别把换行符带进去。还有一种情况是 Key 被删了但配置没更新,去控制台确认 Key 还在。
local proxy failed / connection refused:这类报错通常出现在 Hermes 启动阶段,说明它连不上配置的地址。检查网络是否能访问taotoken.net,以及配置文件里有没有写错协议(http 写成 https 或反过来)。如果你在服务器上跑,确认服务器出网正常。
reading choices / structured array 相关报错:这是 Scanpy 的经典坑。adata.uns['rank_genes_groups']['names']是一个一维结构化数组,形状是(n_genes,),不是(n_genes, n_clusters)。聚类数要用len(names.dtype.names)拿,访问方式是names[rank][cluster_index]。如果你按二维数组去索引,就会报错。传给画图函数前一定要str()转换:
names = adata.uns['rank_genes_groups']['names'] n_clusters = len(names.dtype.names) top_gene = str(names[0][0])OAuth / 认证失败:如果你在 Hermes 里配了消息平台(比如 QQ 机器人),OAuth 报错和模型 Key 是两回事。先确认模型通道单独能通,再去查平台侧的配对。两者混在一起排查会浪费很多时间。
TypeError: unhashable type:dotplot 的var_names必须是纯 Python 字符串,不能传 numpy 记录类型。统一转成[str(g) for g in gene_list]。
seurat_v3 flavor 报错:flavor='seurat_v3'需要scikit-misc,没装就报错。用默认的flavor='seurat'不需要额外依赖,先跑通再说。
CellTypist 没有 conf_score 列:predictions.predicted_labels的列是['predicted_labels', 'over_clustering', 'majority_voting'],没有单独的置信度列,用majority_voting做簇级别共识即可。另外 CellTypist 必须吃 log 归一化后的数据,不能是 regress 或 scale 过的,所以要从.raw重新建一份。
排障时如果拿不准是接入层还是代码层的问题,先去接入文档核对参数,再用模型对话做一次最小请求,能快速定位问题在哪一层。
6. 把流程沉淀成 Skill:Hermes 相比 OpenClaw 的差异点
跑通一次不算本事,能复用才算。Hermes 有个我觉得很实用的特性:它会自动把分析过程提取成 skill,存在~/.hermes/skills/下面。比如刚才的单细胞流程,会被整理成这样的结构:
single-cell-scanpy/ ├── SKILL.md ├── references/ │ ├── celltypist_pitfalls.md │ └── rank_genes_groups_structured_array.md └── templates/ ├── celltypist_annotation.py └── pbmc3k_pipeline.pySKILL.md里记录了完整的 10 步流程、触发条件、以及那些踩过的坑——比如结构化数组怎么访问、CellTypist 的数据准备要求、dotplot 的字符串转换。下次你再让它跑类似分析,它会直接调用这个 skill,而不是从零生成。
这一点和 OpenClaw 的路线不太一样。OpenClaw 更依赖人工编写 skill,你得自己把流程整理好喂给它;Hermes 则是边做边沉淀,分析过程本身就是 skill 的来源。对生信这种"流程固定但数据千变万化"的场景,自动沉淀省下的重复劳动很可观。
我的建议是:第一次跑通后,去~/.hermes/skills/里翻一下它生成了什么,把不准确的地方手动修一修,然后这份 skill 就是你自己的单细胞分析资产了。以后换数据集,改一下 Step 1 的加载路径就能复用整条流程。
如果你打算长期做这类分析,Coding Plan 会比按次调用更合适;只是验证模型或偶尔跑一次,用模型对话就够了。Key 的管理和创建在 API Keys 页面,接入参数有疑问就查接入文档。把接入层固定下来,把流程沉淀成 skill,剩下的就是数据本身的事了。