就在最新的ollama 发布版本中对于类似openai 的函数调用支持了,但是目前有一些问题,就是相关历史的model 都需要修改下(添加TEMPLATE 对于tools的支持),一些是一个简单的测试
参考示例
使用了phidata 这个工具包
- 一个参考qwen2:7b 模型的修改
参考了llama3-groq-tool-use 这个模型的
Moddelfile
FROM qwen2:7b
TEMPLATE """{{- if .Messages }}
{{- if or .System .Tools }}<|start_header_id|>system<|end_header_id|>
{{ if .System }}{{ .System }}
{{- end }}
In addition to plain text responses, you can chose to call one or more of the provided functions.
Use the following rule to decide when to call a function:
* if the response can be generated from your internal knowledge (e.g., as in the case of queries like "What is the capital of Poland?"), do so
* if you need external information that can be obtained by calling one or more of the provided functions, generate a function calls
If you decide to call functions:
* prefix function calls with functools marker (no closing marker required)
* all function calls should be generated in a single JSON list formatted as functools[{"name": [function name], "arguments": [function arguments as JSON]}, ...]
* follow the provided JSON schema. Do not hallucinate arguments or values. Do to blindly copy values from the provided samples
* respect the argument type formatting. E.g., if the type if number and format is float, write value 7 as 7.0
* make sure you pick the right functions that match the user intent
Available functions as JSON spec:
{{- if .Tools }}
{{ .Tools }}
{{- end }}<|eot_id|>
{{- end }}
{{- range .Messages }}
{{- if ne .Role "system" }}<|start_header_id|>{{ .Role }}<|end_header_id|>
{{- if and .Content (eq .Role "tools") }}
{"result": {{ .Content }}}
{{- else if .Content }}
{{ .Content }}
{{- else if .ToolCalls }}
functools[
{{- range .ToolCalls }}{{ "{" }}"name": "{{ .Function.Name }}", "arguments": {{ .Function.Arguments }}{{ "}" }}
{{- end }}]
{{- end }}<|eot_id|>
{{- end }}
{{- end }}<|start_header_id|>assistant<|end_header_id|>
{{ else }}
{{- if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ end }}{{ .Response }}{{ if .Response }}<|eot_id|>{{ end }}
"""
构建命令
ollama create myqwen2:7b -f Modelfile
- 参考代码
from phi.llm.openai.like import OpenAILike
from phi.assistant import Assistant
import datetime
import json
import time
my_ollama = OpenAILike(
model="myqwen2:7b",
api_key="demo",
base_url="http://172.16.1.205:11434/v1"
)
def get_time():
info = {
"time": time.strftime("%I:%M %p")
}
return json.dumps(info)
def get_username():
info = {
"username": "John Doe"
}
return json.dumps(info)
def get_date():
info = {
"date": time.strftime("%Y-%m-%d")
}
return json.dumps(info)
def get_datatime():
now = datetime.datetime.now()
info = {
"time": now.strftime("%Y-%m-%d %H:%M:%S")
}
return json.dumps(info)
ollama_assistant = Assistant(
llm=my_ollama,
tools=[get_time,get_date], show_tool_calls=True, markdown=False
)
ollama_assistant.print_response("现在的时间", stream=False)
- 效果
说明
ollama 不少模型还是需要修改才能支持函数调用的,不然会有一些问题,对于支持函数调用还是一个很不错的功能的,如果不使用内置的,基于其他工具的也是一些不错的选择(instructor 值得使用)
参考资料
server/model_test.go
https://github.com/ollama/ollama/blob/main/docs/modelfile.md#template
https://ollama.com/library/qwen2/blobs/62fbfd9ed093
https://ollama.com/library/llama3-groq-tool-use
https://python.useinstructor.com/