BabyAGI是一个极简但设计精巧的自主智能体框架,它的核心不在于模型本身有多强,而在于任务如何被创建、清洗和排序。整个系统的驱动力来自一个明确的目标描述,框架会围绕这个目标向量不断派生新任务,并根据任务向量与目标向量的相似度重新排列执行顺序。理解这套机制,就理解了任务驱动型智能体的调度内核。

一、BabyAGI的整体任务循环与目标向量的角色
BabyAGI的运行循环由四步组成:执行队首任务、根据执行结果创建新任务、清洗任务队列、重排优先级。这四步每轮循环都会执行一次,任务队列就像一个不断自我进化的待办清单。目标向量在这个过程中扮演裁判的角色,它将用户输入的目标描述通过嵌入模型编码为一个固定维度的语义向量,作为所有优先级计算的基准锚点。
具体来看,目标向量在初始化阶段就被计算并缓存。比如你的目标是“写一篇关于机器学习的综述文章”,框架会调用OpenAI的embedding接口,把这句话转成一个1536维的浮点向量。之后每一个新任务在被创建时,同样会被编码成向量,两个向量之间的余弦相似度越高,说明这个任务与最终目标的语义关联越紧密。
这种设计的巧妙之处在于,智能体不需要理解任务的业务含义,只需要计算向量距离就能判断任务的相对价值。当然这也是它的局限:语义相近不代表逻辑上必要,有时关键的前置任务与目标措辞差异很大,相似度得分反而偏低,这一点在后面的调优部分会详细讨论。
二、任务创建与优先级重排的核心代码逻辑
任务创建环节依赖一次大模型调用。框架把当前任务、执行结果和最终目标组装成提示词,让模型输出若干条新的任务建议。输出被解析成任务列表后,还需要经过清洗环节,利用字符串模糊匹配过滤掉与已有任务重复度过高的项,避免队列无限膨胀。
优先级重排是最能体现目标向量价值的环节。原始的priority_agent会为每个任务生成一个序号,但社区改良版本普遍改用向量相似度方案,稳定性更好且成本更低。下面是一个简化但完整的实现:
import openai
import numpy as np
from collections import deque
def get_embedding(text, model="text-embedding-ada-002"):
resp = openai.Embedding.create(input=[text], model=model)
return resp["data"][0]["embedding"]
def cosine_sim(a, b):
a, b = np.array(a), np.array(b)
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def prioritize(goal, tasks, k=5):
# 目标向量作为基准锚点
goal_vec = get_embedding(goal)
scored = [(t, cosine_sim(goal_vec, get_embedding(t["name"]))) for t in tasks]
# 按相似度降序排列,取前k个
scored.sort(key=lambda x: x[1], reverse=True)
return [t for t, _ in scored[:k]]
这段代码保留了这个分支中最值得借鉴的三个细节:一是目标向量只计算一次,不要在每个任务的循环里重复调用嵌入接口,否则成本和延迟都会翻倍;二是相似度计算要处理零向量边界情况,实际生产中建议加上np.linalg.norm结果小于极小值时的保护;三是k值控制队列规模,BabyAGI默认保留前五个任务,过大会稀释执行焦点,过小则容易漏掉必要的中间步骤。
另外要注意,清洗与排序之间没有严格的先后依赖,但实践中通常先清洗再去重后再排序,因为重复任务如果先参与排序,会白白占用嵌入接口的调用配额,在任务量大时这笔开销相当可观。
三、嵌入模型选型与相似度阈值的调优实践
嵌入模型的选择直接决定排序质量。OpenAI的text-embedding-ada-002是最常见的选择,中文场景下效果也不错;如果对数据隐私有要求,可以换成本地部署的开源模型,比如bge-large-zh或者m3e,这些模型在中文语义相似度任务上的表现已经接近商用接口,且维度更小、推理更快。
模型换用时有一个容易踩的坑:不同模型的向量空间互不兼容,切模型必须全量重算目标向量和所有任务向量。如果你把ada-002算出的目标向量和bge算出的任务向量做余弦相似度,得到的分数毫无意义。稳妥的做法是在任务对象里记录向量所属的模型名,读取时校验一致性,不一致就触发重算。
关于相似度阈值,BabyAGI原始代码其实没有设置硬性门槛,所有任务都参与排序。但实际使用中建议加一道过滤:余弦相似度低于0.3左右的任务可以直接丢弃或降级到待观察队列。因为嵌入模型对完全不相关的文本对给出的分数通常在0.2以下,这个区间内的任务基本是模型幻觉产物,执行它们只会浪费token和API费用。阈值的最终取值要结合具体模型校准,做法是取十组明显相关的任务对和十组明显不相关的任务对,分别计算相似度分布,取两个分布的分界点作为阈值。
总结来说,BabyAGI的任务驱动机制证明了目标向量可以成为自主智能体的调度基准。如果你打算搭建自己的版本,优先把嵌入调用做成本地缓存、选定一个稳定的嵌入模型并校准相似度阈值,这三件事做好之后,整个任务循环的稳定性和成本控制都会上一个台阶。