引言
DeepSeek V3 是一个强大的开源语言模型,而Ollama则提供了便捷的本地部署方案。本文将介绍如何通过自定义Modelfile
为DeepSeek V3
添加函数调用功能,从而支持一些常见的agent
框架。
准备工作
1
2
3
4
5
|
# 确保已经安装了 Ollama
ollama --version
# 拉取 DeepSeek V3 模型
ollama pull deepseek-v3
|
自定义 Modelfile
创建一个新的 Modelfile
1
|
vim deepseek-v3t.modelfile
|
把以下内容复制进去:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
FROM deepseek-v3:latest
TEMPLATE """{{- if .Messages }}
{{- if or .System .Tools }}
{{- if .System }}
{{ .System }}
{{- end }}
{{- if .Tools }}
{{- end }}
{{- end }}
{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1 }}
{{- if eq .Role "user" }}<|User|>
{{- if and $.Tools $last }}
Given the following functions, please respond with a JSON for a function call with its proper arguments that best answers the given prompt.
Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}. Do not use variables.
{{ $.Tools }}
{{- end }}
{{ .Content }}
{{- if $last }}<|Assistant|>{{ end }}
{{- else if eq .Role "assistant" }}
<|Assistant|>
{{- if .ToolCalls }}
<|tool▁calls▁begin|>
{{- range .ToolCalls }}
<|tool▁call▁begin|>
{"name": "{{ .Function.Name }}", "parameters": {{ .Function.Arguments }}}
<|tool▁call▁end|>
{{- end }}
<|tool▁calls▁end|>
{{- else }}
{{ .Content }}
{{- if not $last }}<|end▁of▁sentence|>{{- end }}
{{- end }}
{{- else if eq .Role "tool" }}
<|tool▁outputs▁begin|>
<|tool▁output▁begin|>
{{ .Content }}
<|tool▁output▁end|>
<|tool▁outputs▁end|>
{{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}
{{- end }}
{{- end }}
{{- else }}
{{- if .System }}
{{ .System }}
{{- end }}
{{- if .Prompt }}
<|User|>
{{ .Prompt }}
{{- end }}
<|Assistant|>
{{ .Response }}
{{- if .Response }}{{ end }}
{{- end }}"""
|
使用自定义 Modelfile
1
|
ollama create deepseek-v3t -f deepseek-v3t.modelfile
|
使用示例
任选一个你喜欢的agent
框架,调用 openai 兼容的 sdk,就可以直接使用了。
这里以pydantic-ai为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
from openai import AsyncOpenAI
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
openai_client = AsyncOpenAI(
api_key="test",
base_url="http://localhost:11434/v1",
)
# 如果你创建的模型名称不是 deepseek-v3t,需要自己修改
model = OpenAIModel("deepseek-v3t", openai_client=openai_client)
agent = Agent(
model
)
# 为 agent 添加一个工具函数
@agent.tool
async def get_time():
import datetime
return f"Current time is {datetime.datetime.now()}"
async def main():
response = await agent.run("What time is it?")
print(response)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
|
只要这个代码可以运行,那就说明你已经成功为DeepSeek V3
添加了函数调用功能,即使他没调用你给的工具函数 😀
其他
解决闪退问题
由于DeepSeek
系列模型不支持K-shift
,当上下文达到一定长度时,会导致ollama
闪退。目前ollama
官方还没给出一个比较好的解决方案,这个问题暂时可以通过编辑Modelfile
来规避,你只需要在 Modelfile 中添加下面这两行即可:
1
2
|
PARAMETER num_ctx 24576
PARAMETER num_predict 8192
|
修改后的完整 Modelfile 如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
FROM deepseek-v3:latest
PARAMETER num_ctx 24576
PARAMETER num_predict 8192
TEMPLATE """{{- if .Messages }}
{{- if or .System .Tools }}
{{- if .System }}
{{ .System }}
{{- end }}
{{- if .Tools }}
{{- end }}
{{- end }}
{{- range $i, $_ := .Messages }}
{{- $last := eq (len (slice $.Messages $i)) 1 }}
{{- if eq .Role "user" }}<|User|>
{{- if and $.Tools $last }}
Given the following functions, please respond with a JSON for a function call with its proper arguments that best answers the given prompt.
Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}. Do not use variables.
{{ $.Tools }}
{{- end }}
{{ .Content }}
{{- if $last }}<|Assistant|>{{ end }}
{{- else if eq .Role "assistant" }}
<|Assistant|>
{{- if .ToolCalls }}
<|tool▁calls▁begin|>
{{- range .ToolCalls }}
<|tool▁call▁begin|>
{"name": "{{ .Function.Name }}", "parameters": {{ .Function.Arguments }}}
<|tool▁call▁end|>
{{- end }}
<|tool▁calls▁end|>
{{- else }}
{{ .Content }}
{{- if not $last }}<|end▁of▁sentence|>{{- end }}
{{- end }}
{{- else if eq .Role "tool" }}
<|tool▁outputs▁begin|>
<|tool▁output▁begin|>
{{ .Content }}
<|tool▁output▁end|>
<|tool▁outputs▁end|>
{{- if and $last (ne .Role "assistant") }}<|Assistant|>{{- end }}
{{- end }}
{{- end }}
{{- else }}
{{- if .System }}
{{ .System }}
{{- end }}
{{- if .Prompt }}
<|User|>
{{ .Prompt }}
{{- end }}
<|Assistant|>
{{ .Response }}
{{- if .Response }}{{ end }}
{{- end }}"""
|
然后根据上文给出的命令重新创建模型即可。
DeepSeek R1 也适用吗?
理论上,添加了这个模板之后DeepSeek R1
也可以有工具调用的能力,但是由于模型默认输出的<think>xxx</think>
标签,不一定和常见的agent
框架兼容,所以可能需要一些额外的处理,我也没有测试过,如果你有兴趣,可以试试看。
相关资料