Skip to content

第 1 章 · Agent = 算 + 判

pixiu 锚点:docs/technical/智能体应用框架.md(核心分工)、agent/tools.py(32 个"算"工具)、agent/prompts/system.md(LLM"判"的角色 + 15 条纪律)

开篇:10000 股的佣金,谁来算?

假设你要算一笔交易的成本:10000 股,28.5 元,佣金费率 0.025%(最低 5 元),卖出还要交 0.1% 印花税,A 股是 T+1,分红还要按持有期收税(≤30 天 20%、31-365 天 10%、超过 1 年免税)。

这件事有两种做法:

做法 A:写一段 prompt,让 LLM 算。 做法 B:写一个函数,让代码算。

pixiu 选的是 B。在 backtest/costs.py 里,这些规则被写成确定性的代码,回测引擎调用它,一分钱都不会算错,跑一万次结果一样。

你可能会说:这不是显然吗,谁会让 LLM 算这个?

是的,佣金这种显眼的确定性问题,没人会让 LLM 算。但 agent 工程里真正难的,是那些不显眼的判断——"这只票现在能不能买""我该不该止损""这个利好该不该追"。这些问题里,藏着一半该"算"、一半该"判"的内容,而很多人会把它们一股脑丢给 LLM。

pixiu 做对的第一个、也是最根本的一个判断,就是把这两件事切干净:能确定的交给代码算,需要综合的才交给 LLM 判。 这本书后面所有的设计,都是建立在这一刀之上的。

两种极端,都见过

我在做 pixiu 之前,见过两种极端的做法:

极端一:什么都让 LLM 干。 有人把行情数据、持仓、新闻一股脑塞给 LLM,让它"直接告诉我该买还是该卖"。这种 agent 有三个毛病:贵(每次都要把一堆数据喂给模型)、慢(模型逐字吐)、不可复现(同一个问题问两遍,答案可能不一样)。最要命的是——它还会算错。让 LLM 算"当前持仓的浮盈百分比",它在多只股票、不同成本、不同现价的情况下,算错的概率高得吓人。

极端二:什么都想用规则穷尽。 另一端是传统程序员的本能:写一万条 if-else,把"什么情况下该买"全部固化成规则。这条路也走不通——A 股的政策、情绪、资金博弈,你穷举不完,而且写死的规则碰到新情况就哑火。

pixiu 的答案是两端的中间,但边界清晰

代码(算)         LLM(判)
─────────         ─────────
策略回测           读政策判断风向
信号扫描           读新闻判断情绪
持仓盈亏计算        综合多维度给建议
成本/T+1/税费       解释"为什么"
审计合规检查        提醒心理偏差

docs/technical/智能体应用框架.md 里有一句我自己的原话,把这件事说死了:

核心分工:pixiu 负责"算"(确定性计算),LLM 负责"判"(综合判断)。不追求用代码规则穷尽所有交易信号,而是让 LLM 基于量化锚点 + 定性信息做决策。

代码里看这一刀

你打开 pixiu 的源码,这一刀切得清清楚楚。

"算"全在 agent/tools.py 的 32 个工具里。 随便挑几个看它们的描述:

  • run_backtest —— "运行策略回测……考虑 T+1、佣金、印花税、分红"
  • scan_signals —— "扫描交易信号,判断标的当前应买入/卖出/持有"
  • get_portfolio —— "查看投资组合的持仓和盈亏概览"
  • assess_fundamentals —— "综合基本面评估……给出'质地优秀/良好/一般/偏弱'总判断"

注意到了吗——这些都是有确定答案的计算。LLM 调用它们,拿到的是数据,不是观点。工具负责把"算"的结果吐给 LLM,LLM 拿着这些确定的锚点去做"判"。

"判"全在 agent/prompts/system.md 的角色定义里。 pixiu 给 LLM 的角色是:

你是貔貅,一位 A 股投资研究分析师 + 纪律监督员。你的定位:你是"超级研究员",用户是"基金经理"。你负责分析和提醒,最终决策权在用户手里

这个角色本身就是"判"——分析师负责综合信息给判断,监督员负责提醒纪律。"判"这件事,被明确定义成了 LLM 的职责,而不是让它顺便把"算"也干了。

15 条纪律:用"算"约束"判"

这里有个特别精妙的设计,值得单独说。

LLM 的"判"是软的、会飘的。今天让它判"这只票能不能买",它可能因为新闻里一句利好就放行;明天同样的票,它可能谨慎起来。这种飘动,在投资场景里是危险的。

pixiu 的解法是:把不可妥协的纪律,硬编码进"算"的层面,反过来约束"判"。

system.md 里有 15 条硬性风险底线,比如:

  1. 不追涨——当天已涨 5% 以上的标的不建议买入
  2. 卫星仓 8% 止损——到了就走,不犹豫、不侥幸、不分析原因
  3. 总仓位上限——永远保留至少 10% 现金
  4. 新标的必须先回测——用 run_backtest 验证策略在该标的上至少 2 年的表现

这 15 条不是"建议",是红线。它们用代码层的确定性,给 LLM 的"判"画了不可逾越的边界。LLM 可以在边界内自由判,但越界的建议,系统不放过它。

这是一个非常重要的认知:"算"不只是给"判"提供数据,它还能给"判"立规矩。 你越是用确定性的代码把红线焊死,LLM 的"判"就越安全。

为什么非这么切(三个理由)

为什么 pixiu 要把算和判分得这么开?三个硬理由:

1. 确定性。 回测结果必须可复现——同一个策略、同一只票、同一时段,跑一百次结果都得一样,因为 T+1、佣金、印花税、分红税算错一分钱都不行。这种事让概率模型干,是在给自己埋雷。pixiu 的回测引擎有完整的单元测试(那次为了修 T+1 和买入成本的 bug,我重写了 12 个测试用例,见对话 1bf02600)。

2. 成本和速度。 算一盘回测是本地毫秒级计算;让 LLM 算同样的东西,要发请求、等响应、还可能算错。pixiu 的 compare_strategies 一次跑 8 个策略横向对比,全是本地算,瞬间出结果——这种活给 LLM 干又慢又贵。

3. 可测性。 "算"能写单元测试,错就是错,对就是对;"判"只能用 eval 做统计检验(pass_rate、一致率)。把该算的剥离出来,你才有机会给它们写硬测试,而不是把所有东西都扔进 eval 的概率糊里。

边界是活的:判里有算,算里也有判

别把"算"和"判"理解成非黑即白。真实的边界是活的:

判里有算。 LLM 判"海康威视能不能加仓"时,它会主动调用 compare_strategies(算)跑 8 个策略,拿着回测结果支撑它的判断。这就是为什么第 3 章我们会讲"工具粒度"——你要给 LLM 提供不同粗细的"算",让它按需取用。

算里也有判的影子。 scan_signals 有个 fusion 模式,是 8 个策略投票 + 置信度评分。投票本身是确定性计算,但"多策略融合"这个设计,其实是在用"算"的方式模拟一种群体判断。不过它依然是确定的——同样的输入,8 票怎么投永远一样。

所以更准确的说法是:算和判是一条光谱的两端,pixiu 的原则是把能往"算"那端推的,都推过去;只有必须"判"的,才留给 LLM。

这一章的工具:算判分工自检

拿你自己的 agent 项目,回答这几个问题:

  • [ ] 你的 agent 里,有没有本该用代码算、却交给了 LLM 的事?(典型信号:LLM 输出里有"计算结果",而且这个结果必须是确定的)
  • [ ] 反过来,有没有你试图用规则穷尽、其实该交给 LLM 判的事?(典型信号:if-else 嵌套越来越深,还在不断加分支)
  • [ ] 你的 LLM 的"判",有没有被确定性的"红线"约束?(还是说它想怎么判就怎么判,毫无边界?)

如果第一题你勾了"有",这是最该先修的——把确定性的算从 LLM 手里拿回来。这是 ROI 最高的一步。

小结

算判分离,是 agent 工程的第一刀。

这一刀切好了,后面的 prompt、context、harness、loop 才有清晰的职责边界:prompt 讲的是 LLM 怎么"判",context 是"判"的素材,harness(工具)是"算"的入口,loop 是把"判"和"算"串起来的循环。

下一章,我们就沿着这条线,看看这四层在 pixiu 里分别长什么样——以及你怎么判断自己卡在了哪一层。

下一章

第 2 章 · 四阶认知在 pixiu 的落点 —— prompt / context / harness / loop,每一层都用 pixiu 的真实代码讲清楚。