2026-05-10

关于DeepSeek API的一些想法

最近写一个AgentCLI原型玩具的时候,发现一些比较有意思的点.

因为主要是照着DeepSeek API来写的.
所以基本上也可以说是OpenAI Chat Completion API的一些点.
不过,可能有些是DeepSeek特有的.

一个是请求的stop list.
大致就是遇到给定词的时候,模型会停止生成.

这个某种程度上来说,提供了手动接入模型context方向的能力.

之前翻Anthropic早年的几篇博客的时候有提到一个理论.
大致就是llm不单单是predicate next token.

形式上,前面的token对后面token的走向是有某种差分关系的.
也就是说,intuition里,前面token的组织形式,影响着后面token的概率空间.
从而对context的概率空间有着同样的影响.

通俗地说,就是理论上是有可能通过token的组织形式,让后续的模型的attention能够集中在某些特定的知识/context维度,从而提高对结果走向的确定性.

这个也是prompt/personality的理论基础.

一个比较实用场景可能就是最初DeepSeek R1的那个 aha moment.

现在看Flash的thinking在发现错误的时候经常会有先导的hmm,或者but wait用词习惯.

理论上来说,在这个时候停止生成,然后人工amend一个后续的矫正思路的,是有可能帮助CoT提早converge到解决问题的概率空间方向的.

另外一个则是response里的stop reason.

这个主要是sse/stream模式下的一个概念.
也是tool call的主要实现方式.

它也是在tool call的时候,会生成这个stop reason,然后停止sse/token的继续生成.
因为这个时候需要client端去做实际的tool call,然后再把结果以role=tool的形式append回去继续生成,直到真正的推理完成.

直觉上来说,它应该跟请求的stop word是同类东西.

毕竟理论上,要让模型能够产生tool call,形式上也是只要让它学会生成<tool_call>之类的特殊token/标签就行了.

不过这个stop带来的是agent loop的一些思路.

从实现上来说,agent loop要多久,取决于要不要忽略这种stop generation,继续程序上让它loop下去就行了.
最简单的就是在当前turn stop之后,简单追加一个anything else的user prompt就可以继续持续让它生成.
这个比复杂的prompt调教确定性高多了.

而且一般的harness思路也不过就是通过prompt的方式去构建这种audit+retry的workflow.

这个不是说不行.
但是比较挑模型.

尤其像DeepSeek v4 Flash这种喜欢一条路走到黑,一般不遵循subagent指令,就喜欢硬扛,上下文越长能力越强的就不行了.
 
所以感觉还是要有一些类DSL的inner implement来做,会比单纯的prompt来做更合适.

甚至直接面向tool call,把agent model切换/调度/fork做成tool的话,比单纯的单个task tool可能更flexible.

尤其考虑想opus系列那种看上去就是靠偷偷多路采样提高最终接受度的方式.

原则上,对于同一conversation,可以fork多个agent不同model去并发执行,然后采用类似的方式去audit各个返回结果,然后择一作为main/base,继续下一个prompt.

坏处可能就是费token,以及对一些非可重入对tool调用会带来一些反复.
比如不同的model修改同一文件,导致各自的上下文中这个文件的状态总是不对/跟预期不符.

一个折中的方式可能就是在各自stop reason的时候去仲裁,即使是reason是tool call.

还有一个另外可能比较有价值的就是fill in the middle和prefix这两个API变种.

这两个形式上都是实现一个事情,就是给定prefix和stop word,模型生成中间的部分.

这个看着像是某种RL过程的副产品.

因为这个明显可以直接拿来生成各种evaluation.

一个更实用的方式可能就是根据这个做有限度的prompt适配调优/benchmark.

因为它提供了前置和后置部分.
当用不同prompt的时候,前置除了假装system prompt的部分外,其他都是一致的.
后缀也是.

那么中间实践填充的就可以作为某种prompt优劣的基线来源了.

毕竟这种至少后缀是某种确定不变的验收标准.
不算彻底的盲测.

再一点比较有意思的是v4对thinking模式下的有tool call的reasoning内容的处理.
非thinking模式下,reasoning的内容在sse turn之间是可以不必要回传的.

也就是说,非thinking模式下,client端在请求中可以不回传部分内容.也就是交互的input token可以是不一样的.

从实现角度来说,在不考虑缓存的情况下,一样不一样没区别,毕竟都是next token predication.

但是如果强调可以不回传的话,也就是说这个非thinking模式下的reasoning可能不会影响kv cache的内容.
换句话来说,就是这个reasoning可能跟上下文完全没有关系/影响.

那很自然的一个想法就是,非thinking 模式下的reasoning内容是怎么来说,以及到底有什么作用.

记得v4的technical report里提到的各种thinking模式的区别.
非thinking的response格式是</thinking> summary
high的是<thinking>thinking token</thinking>summary
max的是system prompt<thinking>thinking token</thinking>summary

看比较明显的区别就是非thinking是个half close的标签.

能想到的可能就是thinking模式下的tool call生成可能主要是跟thinking的内容有关.
或者说,thinking决定的tool call的概率空间.

不过既然是关于有么有tool call的情况.
那么实际可能纯粹就是thinking模式下,thinking block内过程中也支持tool call.
而非thinking模式里,reasoning是纯粹的CoT,不会生成任何tool call,完全没有外部影响干扰的.

所以从sse层面来说,非thinking的assistant message不会被tool call stop分割.
而thinking的有可能会.
如果不回传的话,server端的拼接可能会有问题?

不过这也只能是猜测了.


关于DeepSeek API的一些想法

最近写一个AgentCLI原型玩具的时候,发现一些比较有意思的点. 因为主要是照着DeepSeek API来写的. 所以基本上也可以说是OpenAI Chat Completion API的一些点. 不过,可能有些是DeepSeek特有的. 一个是请求的stop list. 大致...