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. 大致...