对话前缀续写
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