如何用FastAPI和Ollama搭建一个智能查天气助手?
摘要:春节时看到公众号有个留言:“能不能搞个AI助手,要能聊天气、查限行,还得私有部署。” 别慌!这篇手记用FastAPI + Ollama + 开源模型,加上一点点天气数据微调,跑通一个能对话查询天气的dem
📝 摘要: 春节时看到公众号有个留言:“能不能搞个AI助手,要能聊天气、查限行,还得私有部署。” 别慌!这篇手记用FastAPI + Ollama + 开源模型,加上一点点天气数据微调,跑通一个能对话查询天气的demo。全程口语化,附代码、踩坑记录,直接可以搬到你的项目里。
🚨 一、公众号留言
我盯着手机,脑子里闪过一万个念头:从头训练?没卡;调API?数据出局;用开源模型?怎么让它懂实时天气?
这场景是不是特眼熟?别问我怎么知道的,上周我刚经历过。好在折腾几天总算跑通了,今天就把这套FastAPI + Ollama + 微调的组合拳拆给你看,代码直接复制,改改就能用。
🗺️ 二、先画张地图:我们要干三件事
🔹 第一 —— 用Ollama跑一个开源大模型(比如qwen2.5:3b),让它能对话。
🔹 第二 —— 给模型装个“工具包”:通过FastAPI调用天气API,实现实时查询。
🔹 第三 —— 用过去一年的天气数据做个LoRA微调,让模型更懂天气问答的口气。
🔹 附赠 —— 用Docker Compose一键启动,扔给运维同事不吵架。
⚙️ 三、地基:Ollama + FastAPI 极简搭
Ollama 这东西,我愿称之为“大模型界的Docker”,一行命令拉模型,一行命令起服务。咱们先用它跑个轻量模型:
# 安装ollama(mac/linux都有脚本,windows有exe)
curl -fsSL https://ollama.com/install.sh | sh
# 拉取一个3b模型,够用还不吃显卡
ollama pull qwen2.5:3b
# 启动服务(默认11434端口)
ollama serve
接下来是FastAPI,它就像个智能接线员,把用户的提问转给大模型,再把模型回话包装成API。先写个最简版本:
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
import httpx
app = FastAPI()
OLLAMA_URL = "http://localhost:11434/api/generate"
class ChatRequest(BaseModel):
message: str
@app.post("/chat")
async def chat(req: ChatRequest):
async with httpx.AsyncClient() as client:
payload = {
"model": "qwen2.5:3b",
"prompt": req.message,
"stream": False
}
resp = await client.post(OLLAMA_URL, json=payload)
return {"reply": resp.json()["response"]}
⚠️ 踩坑预警: 我第一次写忘了加stream=False,结果返回了一堆流式chunk,前端直接崩了。记住,简单demo就别开流式了。
🌤️ 四、让模型学会“查天气”:工具调用 + 微调双保险
现在模型只会瞎聊,得让它知道:当用户问天气时,要去调外部API。有两种路子:
🔸 方法A:函数调用(function calling) —— 让模型输出特定格式,我们解析后调接口。简单直接,适合快速验证。
🔸 方法B:微调(fine-tuning) —— 用一批天气问答数据训练模型,让它内化“查天气”这个动作。效果更自然,但需要数据。
我两个都试了,最后用了“微调+工具调用”混搭——微调让模型更主动问地点,工具调用保证数据实时。先看工具调用咋写:
# 给ollama的prompt里加入工具描述
SYSTEM_PROMPT = """
你是一个天气助手。当用户询问天气时,你必须输出JSON格式的查询参数,例如:{"city": "北京"}。我会根据这个参数去调用天气API,然后把结果给你,你再生成自然语言回复。
