在实际 AI 应用开发中,很多场景需要大语言模型能够调用外部工具来执行特定任务,比如读取本地文件、查询数据库或调用 API。传统做法通常依赖云端 API,但数据隐私和网络延迟成为瓶颈。Ollama 作为本地化部署的开源平台,让开发者能在自己的机器上运行轻量级大模型,并结合工具调用能力构建私有化 AI 应用。本文将围绕如何利用 Ollama 训练一个 26M 超轻量级工具调用模型,完成从环境准备、模型微调到本地工具集成的全流程实战。
这个方案特别适合对数据隐私要求高、需要离线运行或希望低成本实验工具调用能力的团队。26M 参数量的模型在消费级显卡上即可完成微调,部署成本远低于百亿级模型,同时保留了基础的工具调用与逻辑推理能力。下面我们会先梳理工具调用的核心概念,再逐步搭建环境、准备数据、完成微调,最后验证模型能否正确调用我们定义的本地文件搜索工具。
1. 理解 Ollama 工具调用的工作机制
工具调用(Tool Calling)本质上是大语言模型与外部环境交互的桥梁。模型接收到用户请求后,并不直接生成答案,而是先判断是否需要调用工具,选择合适工具,生成调用参数,等待工具返回结果,最后整合信息生成最终回复。这种机制让模型能够突破训练数据的时间限制,获取实时信息或执行具体操作。
Ollama 的工具调用框架基于函数调用(Function Calling)规范。开发者需要预先定义一组工具,每个工具包含名称、描述、参数 schema 和实际执行函数。当用户输入到达模型时,Ollama 会将工具描述信息注入上下文,模型根据当前问题决定是否调用工具、调用哪个工具以及传递什么参数。工具执行后的结果再返回给模型,由模型生成面向用户的自然语言回复。
与云端 API 调用相比,Ollama 本地部署的优势在于整个流程都在本地完成,无需网络传输,数据完全私有。26M 模型虽然参数量小,但通过有针对性的微调,完全可以学会基础的工具选择与参数生成能力。下面我们开始准备实验环境。
2. 环境准备与 Ollama 安装配置
2.1 硬件与系统要求
本地部署微调对硬件有一定要求,但 26M 模型相对轻量,以下是最低配置建议:
CPU : 四核以上,支持 AVX2 指令集
内存 : 16GB RAM(微调过程中需要缓存训练数据)
显卡 : 可选,如果有 NVIDIA GPU(6GB+ 显存)可显著加速训练
磁盘 : 10GB 可用空间(用于存储模型权重和训练数据)
操作系统 : Windows 10/11, macOS 12+, 或 Linux(Ubuntu 20.04+)
实际测试中,搭载 RTX 3060(12GB)的台式机或 M2 芯片的 MacBook 都能流畅运行整个流程。
2.2 安装 Ollama
Ollama 提供了各平台的简易安装包,访问官网 https://ollama.com/download 选择对应版本下载安装。
Windows 系统 :
下载 .exe 安装程序,以管理员身份运行
安装完成后,Ollama 会作为服务自动启动
打开命令提示符,验证安装:ollama -v
macOS 系统 :
下载 .dmg 文件,拖拽到 Applications 文件夹
首次运行需要在系统偏好设置中授权
终端验证:ollama -v
Linux 系统 :
BASH
复制
2
curl -fsSL https://ollama.com/install.sh | sh
如果下载速度较慢,可以配置国内镜像源加速。创建或修改 ~/.ollama/ollama.yaml 文件(Linux/macOS)或 C:\Users\<用户名>\.ollama\ollama.yaml(Windows):
YAML
复制
2
registry: "registry.ollama.com"
4
- location: "https://mirror.example.com/ollama"
2.3 安装 Python 依赖
工具调用示例需要 Python 环境(3.8+)和必要的库:
BASH
复制
2
python -m venv ollama_env
3
source ollama_env/bin/activate
7
pip install ollama pymupdf
ollama: 官方 Python SDK,用于与本地 Ollama 服务交互
pymupdf: PDF 文件解析库,用于工具函数中读取文档内容
3. 准备微调数据与工具定义
3.1 设计工具调用训练数据
微调小模型的关键在于高质量的训练数据。对于工具调用任务,我们需要准备问答对,其中包含工具选择、参数生成和结果整合的完整链条。数据格式参考:
JSON
复制
5
"content" : "帮我找一下关于机器学习的文档"
12
"name" : "search_text_files" ,
21
"content" : "./files/ml_tutorial.pdf" ,
22
"tool_call_id" : "call_001"
26
"content" : "找到相关文档:ml_tutorial.pdf"
实际项目中,可以编写脚本批量生成此类数据,覆盖各种工具调用场景。关键是要让模型学会:
何时需要调用工具(而不是直接回答)
如何选择最合适的工具
如何从用户问题中提取关键参数
如何将工具返回结果转化为自然语言回复
3.2 定义本地工具函数
工具函数是模型与外部环境交互的接口。我们先定义两个简单的文件搜索工具:
PYTHON
复制
4
def search_text_files (keyword: str ) -> str :
6
在指定目录的文本文件和PDF中搜索包含关键词的文档
10
if not os.path.exists(directory):
13
for fname in os.listdir(directory):
14
filepath = os.path.join(directory, fname)
15
if os.path.isfile(filepath) and not fname.startswith('.' ):
17
if fname.endswith(".pdf" ):
18
doc = pymupdf.open (filepath)
21
document_text += page.get_text()
25
if keyword.lower() in document_text.lower():
29
elif fname.endswith(".txt" ):
30
with open (filepath, 'r' , encoding='utf-8' ) as f:
32
if keyword.lower() in content.lower():
36
def search_image_files (keyword: str ) -> str :
41
directory = "./files/"
42
image_extensions = (".jpg" , ".png" , ".jpeg" , ".gif" )
44
for fname in os.listdir(directory):
45
if fname.lower().endswith(image_extensions):
46
filepath = os.path.join(directory, fname)
49
if keyword.lower() in fname.lower():
3.3 配置 Ollama 工具 Schema
工具定义需要转换为 Ollama 能理解的 JSON schema:
PYTHON
复制
5
'name' : 'search_text_files' ,
6
'description' : '在本地文件系统中搜索包含特定关键词的文本文件或PDF文档' ,
12
'description' : '从用户请求中提取的搜索关键词' ,
15
'required' : ['keyword' ],
22
'name' : 'search_image_files' ,
23
'description' : '在本地文件系统中搜索包含特定内容的图像文件' ,
29
'description' : '从用户请求中提取的图像内容关键词' ,
32
'required' : ['keyword' ],
39
available_functions = {
40
'search_text_files' : search_text_files,
41
'search_image_files' : search_image_files
工具描述(description)的质量直接影响模型的选择准确性,要清晰说明工具的用途和适用场景。
4. 选择与微调 26M 超轻量级模型
4.1 模型选型考虑
26M 参数量属于超轻量级,适合工具调用这类相对结构化任务。可选模型包括:
TinyLlama-1.1B 的裁剪版(26M 参数定制)
Microsoft Phi-2 的小参数变体
自研的 26M 工具调用专用模型
由于公开的 26M 模型较少,实践中往往需要从更大的模型蒸馏或从头训练。这里以 TinyLlama 为基础进行参数裁剪和微调。
4.2 准备模型微调环境
Ollama 支持通过 Modelfile 定义和构建自定义模型:
DOCKERFILE
复制
5
PARAMETER num_attention_heads 4
6
PARAMETER hidden_size 256
7
PARAMETER intermediate_size 512
8
PARAMETER num_hidden_layers 6
11
SYSTEM """你是一个工具调用助手,能够根据用户需求调用合适的工具。"""
14
TEMPLATE """{{ if .System }}<|system|>{{ .System }}</s>{{ end }}{{ if .Tools }}<|tools|>{{ .Tools }}</s>{{ end }}{{ if .Prompt }}<|user|>{{ .Prompt }}</s>{{ end }}{{ if .Response }}<|assistant|>{{ .Response }}</s>{{ end }}"""
构建自定义模型:
BASH
复制
1
ollama create tool-call-26m -f ./Modelfile
4.3 执行模型微调
使用准备好的工具调用数据对模型进行监督微调:
PYTHON
复制
5
with open ('tool_call_data.jsonl' , 'r' ) as f:
6
training_data = [json.loads(line) for line in f]
10
'model' : 'tool-call-26m' ,
11
'training_data' : training_data,
14
'learning_rate' : 5e-5 ,
21
response = ollama.fine_tune(**fine_tune_config)
22
print (f"微调任务ID: {response['job_id' ]} " )
23
except Exception as e:
24
print (f"Ollama 微调API暂未开放,可使用传统方法微调" )
如果 Ollama 原生微调功能不可用,可以使用 Hugging Face Transformers 库进行微调,再将权重转换为 Ollama 格式:
PYTHON
复制
1
from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments
4
model = AutoModelForCausalLM.from_pretrained("TinyLlama/TinyLlama-1.1B" )
5
tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B" )
8
training_args = TrainingArguments(
9
output_dir="./tool_call_26m" ,
11
per_device_train_batch_size=4 ,
5. 验证工具调用流程与效果
5.1 启动 Ollama 服务并加载模型
确保 Ollama 服务在后台运行:
PYTHON
复制
5
def start_ollama_service ():
11
subprocess.Popen(["ollama" , "serve" ],
12
stdout=subprocess.DEVNULL,
13
stderr=subprocess.STDOUT)
16
start_ollama_service()
20
ollama.pull('tool-call-26m' )
5.2 完整工具调用流程测试
PYTHON
复制
1
def run_tool_call_pipeline (user_input ):
5
messages = [{'role' : 'user' , 'content' : user_input}]
8
response = ollama.chat(
16
if hasattr (response.message, 'tool_calls' ) and response.message.tool_calls:
17
for tool_call in response.message.tool_calls:
18
tool_name = tool_call.function.name
19
if tool_name in available_functions:
20
print (f"调用工具: {tool_name} , 参数: {tool_call.function.arguments} " )
23
tool_func = available_functions[tool_name]
24
result = tool_func(**tool_call.function.arguments)
25
tool_results.append(f"{tool_name} 返回: {result} " )
29
messages.append(response.message)
30
tool_response = "工具执行结果: " + "; " .join(tool_results)
31
messages.append({'role' : 'tool' , 'content' : tool_response})
33
final_response = ollama.chat('tool-call-26m' , messages=messages)
34
return final_response.message.content
36
return response.message.content
45
for query in test_queries:
47
result = run_tool_call_pipeline(query)
48
print (f"助手: {result} \n" )
5.3 预期输出与效果评估
正常情况下的输出示例:
TEXT
复制
2
调用工具: search_text_files, 参数: {'keyword': 'Python编程'}
3
助手: 找到相关文档: ./files/python_tutorial.pdf
6
调用工具: search_image_files, 参数: {'keyword': '机器学习'}
7
助手: 未找到匹配的图片文件,请尝试其他关键词
评估指标应包括:
工具选择准确率 :模型是否在需要时调用工具,并选择正确工具
参数生成质量 :从用户问题中提取的关键词是否相关
结果整合能力 :能否将工具返回结果转化为自然语言回复
6. 常见问题排查与优化建议
6.1 工具调用失败场景分析
问题现象
可能原因
检查方式
解决方案
模型不调用任何工具
工具描述不清晰或训练数据不足
检查工具描述是否准确
优化工具描述,增加相关训练样本
工具选择错误
工具功能描述重叠或区分度不够
对比不同工具的描述
明确各工具专属场景,增加区分度
参数提取不准
模型不理解如何从问题提取参数
分析错误参数案例
在训练数据中加强参数提取示例
工具执行但结果无用
工具函数逻辑有问题
单独测试工具函数
修复工具函数bug,增加日志
6.2 性能优化建议
针对 26M 小模型的优化策略 :
简化工具描述 :用最简练的语言描述工具功能,减少上下文长度
限制工具数量 :小模型同时处理多个工具能力有限,优先保证核心工具质量
参数约束 :明确参数类型和范围,降低模型生成难度
结果格式化 :工具返回结果尽量结构化,方便模型解析
PYTHON
复制
6
'name' : 'search_text_files' ,
7
'description' : '搜索文档:输入关键词,返回匹配文件路径' ,
13
'description' : '搜索关键词,如"Python"或"机器学习"' ,
16
'required' : ['keyword' ],
6.3 生产环境部署考量
当工具调用模型准备投入实际使用时,还需要考虑:
错误处理机制 :工具执行失败时的降级方案
超时控制 :设置工具调用超时,避免长时间等待
权限管理 :限制工具可访问的资源范围
日志监控 :记录完整的工具调用链路用于排查问题
PYTHON
复制
1
def safe_tool_call (tool_func, args, timeout=30 ):
5
def timeout_handler (signum, frame ):
6
raise TimeoutError("Tool execution timeout" )
9
signal.signal(signal.SIGALRM, timeout_handler)
12
result = tool_func(**args)
15
except Exception as e:
16
return f"Tool error: {str (e)} "
7. 扩展方向与进阶实践
基于基础的文本和图像搜索工具,可以进一步扩展模型能力:
7.1 集成更多工具类型
数据库查询工具 :让模型能执行SQL查询获取结构化数据
API调用工具 :集成天气查询、股票信息等外部API
计算工具 :执行数学计算、单位转换等任务
系统操作工具 :文件管理、进程监控等(需严格控制权限)
7.2 多工具协同调用
训练模型学会按顺序调用多个工具完成复杂任务:
PYTHON
复制
2
multi_tool_sequence = [
3
{"tool" : "search_text_files" , "args" : {"keyword" : "销售报告" }},
4
{"tool" : "extract_summary" , "args" : {"file_path" : "<上一步结果>" , "max_length" : 200 }}
7.3 工具调用缓存优化
为提升响应速度,可以添加工具结果缓存:
PYTHON
复制
1
from functools import lru_cache
3
@lru_cache(maxsize=100 )
4
def cached_search_text_files (keyword: str ) -> str :
6
return search_text_files(keyword)
26M 超轻量级工具调用模型虽然能力有限,但通过精心设计的工具集和有针对性的微调,完全可以在特定场景下替代部分人工操作。这种本地化部署方案特别适合对数据隐私要求高、预算有限的中小团队。随着模型规模增大和训练数据丰富,工具调用的准确性和复杂性还能进一步提升。
实际项目中,建议先从最简单的工具开始验证流程,逐步增加工具复杂度和模型规模。每次变更后都要充分测试,确保模型能正确理解工具功能并生成合适的参数。工具调用能力的构建是一个迭代过程,需要不断根据实际使用反馈优化工具设计和训练数据。