对话前缀续写

DeepSeek关于对话前缀续写的官方说明地址:

https://api-docs.deepseek.com/zh-cn/guides/chat_prefix_completion/

在日常开发中,你有没有遇到过这些烦恼:

让AI写代码,它非要先回一句:“好的,这是为您生成的代码:”。

让 AI 输出 JSON,它有时自作主张包一层 {"data": [...]},甚至夹杂解释文字。

设定AI扮演特定角色,它每次都要先啰嗦一句“我明白了”,让人立即出戏。

要彻底根治这些“AI 废话”,最好的办法不是写更严厉的提示词,而是使用 DeepSeek 提供的高级功能:对话前缀续写。

对话前缀续写的本质

对话前缀续写的本质:让用户接管模型的第一句话,强制模型顺着你写的话往下编。

通常大模型是“你问一句,我答一句”;而前缀续写是,你在 Messages 数组的最后,强行塞入一条role为assistant的消息作为开头,模型就会被迫接着这个开头把剩下的内容写完。

和stop参数一起使用

在大模型语料中,代码块通常使用 Markdown 语法包裹(即 ```python 开头,``` 结尾)。

如果我们在前缀中直接塞入 ```python,等于告诉 AI:“代码框我已经帮你敲好了,你直接在里面写代码即可。” 这样 AI 就绝对不可能再说废话。

同时,为了防止 AI 写完代码后继续啰嗦,我们必须配合 stop 参数(停止词)。只要 AI 敲出结尾的 ```,接口就会立刻截断输出,交给你一段干干净净的纯代码。

两个专用属性

为了让用户用最简单的方式实现对话前缀续写,LLMCaller封装了两个专属属性:

PrefixContent:设置前缀的具体内容 如: "```python" & vbCrLf

PrefixKey:设置前缀在请求体中的参数名,默认 "prefix",如果使用千问或kimi,需要将其改为"partial",具体请查看大模型的文档。

示例一

输出纯代码,彻底消灭废话:

Dim caller As New LLMCaller("https://api.deepseek.com/beta/chat/completions", "deepseek-flash", "sk-a734b83536da45e9aedc3e42605bfb3a")
caller.UserMessage =
"请写一个快速排序的Python代码"
caller.PrefixContent =
"```python" & vbCrLf '指定前缀
caller.stop =
New JArray() From {"```"} '指定停止词,这是一个数组,最多可指定四个停止词
If
caller.GetResult() Then
    MessageBoxA.Show(caller.Result)

Else

    MessageBoxA.Show(caller.Error)

End
If

重要提示:和其他大模型不同,Deepseek需要使用专门的请求地址 来开启对话前缀续写功能(注意地址中的 /beta/)

示例二

沉浸式角色扮演,直接进入剧情:

Dim
caller As New LLMCaller("https://api.deepseek.com/beta/chat/completions", "deepseek-flash", "sk-a734b83536da45e9aedc3e42605bfb3a")
caller.SystemPrompt =
"你正在扮演角色。请直接输出角色的台词内容,绝不要包含任何动作描写、心理描写、旁白或解释说明"
caller.UserMessage =
"林妹妹,这天气如何?"
caller.PrefixContent =
"林黛玉轻咳了两声,用手帕掩住嘴角,幽幽地说道"
If
caller.GetResult() Then
    MessageBoxA.Show(caller.PrefixContent & caller.Result)

Else

    MessageBoxA.Show(caller.Error)

End
If

重要提示:这里没有使用stop参数,因为我们真的不知道林妹妹最后会说什么,也无法预测她会在哪个字停下来,所以这里通过系统提示词解决了废话的问题。

示例三

可以用这个功能实现代码补全,例如:

Dim caller As New LLMCaller("https://api.deepseek.com/beta/chat/completions", "deepseek-flash", "sk-a734b83536da45e9aedc3e42605bfb3a")
Dim
precode As String = <![CDATA[
Public Function Fibonacci(n As Integer) As Integer
    If n <= 1 Then
        Return n
    Else
]]>
.Value
caller.UserMessage =
"补全下面的VB.NET函数,只输出代码,不要任何解释。"
caller.PrefixContent = precode

If
caller.GetResult() Then
   
' 把前缀和模型补全的内容拼在一起,就是完整的函数
    MessageBoxA.Show(caller.PrefixContent & caller.Result)

Else

    MessageBoxA.Show(caller.Error)

End
If

重要提示:前缀和停止词都不会出现在最终结果中,所以需要手工拼接。

有时AI会自作主张,给出多个补全方案,如果只需一个,可以修改代码:

Dim caller As New LLMCaller("https://api.deepseek.com/beta/chat/completions", "deepseek-flash", "sk-a734b83536da45e9aedc3e42605bfb3a")
Dim
precode As String = <![CDATA[
Public Function Fibonacci(n As Integer) As Integer
    If n <= 1 Then
        Return n
    Else
]]>
.Value
caller.UserMessage =
"补全下面的VB.NET函数,只输出代码,不要任何解释。"
caller.PrefixContent = precode
caller.stop =
New JArray() From {"End Function"}
If
caller.GetResult() Then
   
' 把前缀和模型补全的内容拼在一起,就是完整的函数
    MessageBoxA.Show(caller.PrefixContent & caller.Result &
"End Function")
Else

    MessageBoxA.Show(caller.Error)

End
If

示例四

PrefixKey属性的默认值为"prefix",不同的模型使用的值可能不能,例如如果用KIMI,就需要将PrefixKey属性设置为"partial":

Dim caller As New LLMCaller("https://api.moonshot.cn/v1/chat/completions", "kimi-k3", "sk-wL84TQ5VdJmV1FtPLSsQqXVH02QxiPBIWupFlAAOzAc5Owq5")
caller.UserMessage =
"用户反馈:我买的商品三天了还没发货,怎么回事?"
caller.PrefixKey =
"partial" ' Kimi 使用 partial
caller.PrefixContent =
"尊敬的用户您好,"
If caller.GetResult() Then
    MessageBoxA.Show(caller.PrefixContent & caller.Result)

Else

    MessageBoxA.Show(caller.Error)

End
If


本页地址:http://www.foxtable.com/webhelp/topics/7229.htm