Python+Ollama零成本打造一個(gè)私有AI助手
一、為什么要在本地跑大模型?
| 對(duì)比維度 | 云端 API(ChatGPT / Claude) | 本地模型(Ollama) |
|---|---|---|
| 費(fèi)用 | 按量付費(fèi),$20/月起 | 完全免費(fèi) |
| 數(shù)據(jù)隱私 | 數(shù)據(jù)上傳到云端 | 數(shù)據(jù)留在本地 |
| 網(wǎng)絡(luò)依賴(lài) | 必須聯(lián)網(wǎng) | 離線可用 |
| 模型選擇 | 固定 | 自由切換開(kāi)源模型 |
| 硬件要求 | 無(wú) | 需要一定配置 |

二、Ollama 是什么?
Ollama 是一個(gè)開(kāi)源的本地大模型運(yùn)行框架,核心特點(diǎn):
- 一鍵拉取模型:類(lèi)似
docker pull的體驗(yàn) - 自動(dòng)適配硬件:根據(jù)你的顯存/內(nèi)存自動(dòng)量化
- 兼容 OpenAI API 格式:現(xiàn)有代碼幾乎不用改
- 跨平臺(tái):Windows / macOS / Linux 都支持

三、環(huán)境準(zhǔn)備
3.1 硬件要求
| 模型規(guī)模 | 最低內(nèi)存/顯存 | 推薦配置 |
|---|---|---|
| 1.5B~3B(輕量) | 4 GB | 8 GB 內(nèi)存即可 |
| 7B~8B(主流) | 8 GB | 16 GB 內(nèi)存或 8 GB 顯存 |
| 14B~32B(進(jìn)階) | 16 GB | 32 GB 內(nèi)存或 16 GB 顯存 |
| 70B+(旗艦) | 48 GB | 專(zhuān)業(yè)顯卡 / 服務(wù)器 |
沒(méi)有獨(dú)立顯卡也能跑!Ollama 支持 純 CPU 推理,只是速度慢一些。
3.2 安裝 Ollama
# macOS / Linux(一行搞定) curl -fsSL https://ollama.com/install.sh | sh # Windows:前往 https://ollama.com/download 下載安裝包
驗(yàn)證安裝:
ollama --version
# 輸出:ollama version is 0.6.x
3.3 拉取模型
# 推薦:Qwen3 8B(中文能力最強(qiáng)的小模型之一) ollama pull qwen3:8b # 備選:Llama 4 Scout 17B(Meta 最新開(kāi)源模型) ollama pull llama4:scout17b # 輕量選擇:Qwen3 4B(4GB 內(nèi)存就能跑) ollama pull qwen3:4b # 查看已下載的模型 ollama list
3.4 安裝 Python 依賴(lài)
pip install ollama
四、快速上手:5 行代碼跑起來(lái)
4.1 最簡(jiǎn)對(duì)話
import ollama
# 發(fā)送一條消息,獲取回復(fù)
response = ollama.chat(
model="qwen3:8b",
messages=[
{"role": "user", "content": "用 Python 寫(xiě)一個(gè)快速排序算法"}
]
)
print(response["message"]["content"])4.2 流式輸出(打字機(jī)效果)
import ollama
# stream=True 開(kāi)啟流式輸出,體驗(yàn)更絲滑
stream = ollama.chat(
model="qwen3:8b",
messages=[
{"role": "user", "content": "解釋一下 Python 的裝飾器"}
],
stream=True
)
for chunk in stream:
print(chunk["message"]["content"], end="", flush=True)4.3 多輪對(duì)話(保持上下文)
import ollama
# 維護(hù)對(duì)話歷史
messages = []
def chat(user_input: str) -> str:
messages.append({"role": "user", "content": user_input})
response = ollama.chat(model="qwen3:8b", messages=messages)
assistant_msg = response["message"]["content"]
messages.append({"role": "assistant", "content": assistant_msg})
return assistant_msg
# 多輪對(duì)話
print(chat("你好,我正在學(xué) Python"))
print("---")
print(chat("剛才我說(shuō)我在學(xué)什么來(lái)著?")) # 它能記住上下文五、實(shí)戰(zhàn)項(xiàng)目:打造命令行 AI 助手
下面是一個(gè)功能完整的本地 AI 助手,支持多輪對(duì)話、Markdown 渲染、歷史記錄。
5.1 項(xiàng)目結(jié)構(gòu)
local-ai-assistant/
├── assistant.py # 主程序
├── config.py # 配置文件
└── chat_history.json # 對(duì)話歷史(自動(dòng)生成)
5.2 配置文件 config.py
# config.py MODEL_NAME = "qwen3:8b" # 使用的模型 SYSTEM_PROMPT = """你是一個(gè)專(zhuān)業(yè)的 AI 編程助手。 你擅長(zhǎng) Python、數(shù)據(jù)分析、自動(dòng)化辦公。 回答要簡(jiǎn)潔實(shí)用,代碼要可以直接運(yùn)行。""" MAX_HISTORY = 20 # 最多保留的對(duì)話輪數(shù)
5.3 主程序 assistant.py
# assistant.py
import json
import ollama
from datetime import datetime
from config import MODEL_NAME, SYSTEM_PROMPT, MAX_HISTORY
def load_history(filepath="chat_history.json"):
"""加載對(duì)話歷史"""
try:
with open(filepath, "r", encoding="utf-8") as f:
return json.load(f)
except FileNotFoundError:
return []
def save_history(messages, filepath="chat_history.json"):
"""保存對(duì)話歷史"""
with open(filepath, "w", encoding="utf-8") as f:
json.dump(messages, f, ensure_ascii=False, indent=2)
def chat_stream(user_input: str, messages: list) -> str:
"""流式對(duì)話"""
messages.append({"role": "user", "content": user_input})
print(f"\n\033[92m?? AI:\033[0m ", end="", flush=True)
full_response = ""
stream = ollama.chat(model=MODEL_NAME, messages=messages, stream=True)
for chunk in stream:
content = chunk["message"]["content"]
print(content, end="", flush=True)
full_response += content
print("\n")
messages.append({"role": "assistant", "content": full_response})
# 限制歷史長(zhǎng)度
if len(messages) > MAX_HISTORY * 2 + 1:
messages = [messages[0]] + messages[-(MAX_HISTORY * 2):]
return full_response
def main():
print("=" * 50)
print(f" 本地 AI 助手 | 模型: {MODEL_NAME}")
print(" 輸入 /clear 清空歷史 | /quit 退出")
print("=" * 50)
# 初始化對(duì)話
messages = load_history()
if not messages:
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
while True:
user_input = input("\n\033[94m?? 你:\033[0m ").strip()
if not user_input:
continue
if user_input == "/quit":
save_history(messages)
print("?? 再見(jiàn)!對(duì)話已保存。")
break
if user_input == "/clear":
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
save_history(messages)
print("??? 對(duì)話歷史已清空。")
continue
chat_stream(user_input, messages)
save_history(messages)
if __name__ == "__main__":
main()5.4 運(yùn)行效果
python assistant.py
==================================================
本地 AI 助手 | 模型: qwen3:8b
輸入 /clear 清空歷史 | /quit 退出
==================================================
?? 你: 幫我寫(xiě)一個(gè) Python 腳本,監(jiān)控某個(gè)文件夾的變化
?? AI: 好的,使用 `watchdog` 庫(kù)可以輕松實(shí)現(xiàn)文件夾監(jiān)控...
(此處輸出完整代碼)
六、進(jìn)階玩法
6.1 讓 AI 調(diào)用本地函數(shù)(Function Calling)
import ollama
import json
# 定義工具函數(shù)
def get_weather(city: str) -> str:
"""模擬獲取天氣(可替換為真實(shí) API)"""
weather_data = {"北京": "晴天 22°C", "上海": "多云 18°C", "深圳": "大雨 28°C"}
return weather_data.get(city, "未查詢到該城市天氣")
def calculate(expression: str) -> str:
"""安全計(jì)算數(shù)學(xué)表達(dá)式"""
try:
allowed = set("0123456789+-*/.() ")
if all(c in allowed for c in expression):
return str(eval(expression))
return "不安全的表達(dá)式"
except Exception as e:
return f"計(jì)算錯(cuò)誤: {e}"
# 注冊(cè)工具
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "獲取指定城市的天氣信息",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名稱(chēng)"}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate",
"description": "計(jì)算數(shù)學(xué)表達(dá)式",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "數(shù)學(xué)表達(dá)式"}
},
"required": ["expression"]
}
}
}
]
# 工具映射
tool_map = {
"get_weather": get_weather,
"calculate": calculate
}
# 對(duì)話
messages = [{"role": "user", "content": "北京天氣怎么樣?順便幫我算一下 25*36+128"}]
response = ollama.chat(model="qwen3:8b", messages=messages, tools=tools)
# 處理工具調(diào)用
if response["message"].get("tool_calls"):
for tool_call in response["message"]["tool_calls"]:
func_name = tool_call["function"]["name"]
func_args = tool_call["function"]["arguments"]
print(f"?? 調(diào)用工具: {func_name}({func_args})")
result = tool_map[func_name](**func_args)
print(f" 結(jié)果: {result}")6.2 兼容 OpenAI SDK
# 如果你已有使用 OpenAI SDK 的代碼,只需改一行
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:11434/v1", # 指向 Ollama
api_key="ollama" # 隨意填,不影響
)
response = client.chat.completions.create(
model="qwen3:8b",
messages=[
{"role": "user", "content": "Hello, who are you?"}
]
)
print(response.choices[0].message.content)這意味著:所有基于 OpenAI API 的應(yīng)用(LangChain、Dify、Cursor 等)都可以無(wú)縫切換到本地模型!
七、模型選擇指南

模型推薦表
| 使用場(chǎng)景 | 推薦模型 | 大小 | 命令 |
|---|---|---|---|
| 中文對(duì)話 / 寫(xiě)作 | Qwen3 8B | ~5 GB | ollama pull qwen3:8b |
| 英文編程 | Llama 4 Scout | ~10 GB | ollama pull llama4:scout17b |
| 邏輯推理 / 數(shù)學(xué) | DeepSeek R2 8B | ~5 GB | ollama pull deepseek-r2:8b |
| 低配機(jī)器 | Qwen3 1.7B | ~1 GB | ollama pull qwen3:1.7b |
| 代碼專(zhuān)用 | Qwen3-Coder 7B | ~4 GB | ollama pull qwen3-coder:7b |
八、常見(jiàn)問(wèn)題
Q:沒(méi)有顯卡能跑嗎?
A:能。Ollama 支持 CPU 推理,8B 模型在 16GB 內(nèi)存的機(jī)器上完全可以跑,速度約 5-10 token/s。
Q:中文效果好還是英文效果好?
A:推薦 Qwen3 系列,它的中文能力是目前開(kāi)源模型里最強(qiáng)的,遠(yuǎn)超同級(jí)別的 Llama。
Q:和 ChatGPT 比差多少?
A:8B 級(jí)別的模型大約相當(dāng)于 GPT-3.5 的水平,日常問(wèn)答夠用,復(fù)雜推理和長(zhǎng)文本還有差距。如果硬件允許,跑 32B 或 70B 的模型會(huì)更接近 GPT-4 級(jí)別。
Q:商用免費(fèi)嗎?
A:大部分模型(Qwen、Llama、Gemma)允許商用,但建議查看各模型的具體 License。
總結(jié)
Ollama 本地 AI 的核心優(yōu)勢(shì):
├── 零成本 —— 不花一分錢(qián) API 費(fèi)用
├── 零 風(fēng)險(xiǎn) —— 數(shù)據(jù)永遠(yuǎn)不會(huì)離開(kāi)你的電腦
├── 零門(mén)檻 —— pip install + ollama pull,5 分鐘上手
└── 零妥協(xié) —— 兼容 OpenAI API,現(xiàn)有生態(tài)無(wú)縫切換
現(xiàn)在就打開(kāi)終端,花 5 分鐘跑起你的第一個(gè)本地 AI 助手吧。
以上就是Python+Ollama零成本打造一個(gè)私有AI助手的詳細(xì)內(nèi)容,更多關(guān)于Python Ollama開(kāi)發(fā)AI助手的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python 根據(jù)pid殺死相應(yīng)進(jìn)程的方法
下面小編就為大家?guī)?lái)一篇python 根據(jù)pid殺死相應(yīng)進(jìn)程的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
python實(shí)現(xiàn)統(tǒng)計(jì)文本中單詞出現(xiàn)的頻率詳解
這篇文章主要介紹了python統(tǒng)計(jì)文本中單詞出現(xiàn)頻率,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Python PyTorch實(shí)現(xiàn)Timer計(jì)時(shí)器
這篇文章主要為大家詳細(xì)介紹了Python PyTorch如何實(shí)現(xiàn)簡(jiǎn)單的Timer計(jì)時(shí)器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-08-08
Python中函數(shù)的創(chuàng)建與調(diào)用你了解嗎
這篇文章主要為大家詳細(xì)介紹了Python中函數(shù)的創(chuàng)建與調(diào)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
用Python將Excel數(shù)據(jù)導(dǎo)入到SQL Server的例子
今天小編就為大家分享一篇用Python將Excel數(shù)據(jù)導(dǎo)入到SQL Server的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08
Python+Delorean實(shí)現(xiàn)時(shí)間格式智能轉(zhuǎn)換
DeLorean是一個(gè)Python的第三方模塊,基于?pytz?和?dateutil?開(kāi)發(fā),用于處理Python中日期時(shí)間的格式轉(zhuǎn)換。本文將詳細(xì)講講DeLorean的使用,感興趣的可以了解一下2022-04-04
使用Python3實(shí)現(xiàn)判斷函數(shù)的圈復(fù)雜度
編寫(xiě)函數(shù)最重要的原則就是:別寫(xiě)太復(fù)雜的函數(shù),那什么樣的函數(shù)才能算是過(guò)于復(fù)雜?一般會(huì)通過(guò)兩個(gè)標(biāo)準(zhǔn)來(lái)判斷,長(zhǎng)度和圈復(fù)雜度,下面我們就來(lái)看看如何使用Python判斷函數(shù)的圈復(fù)雜度吧2024-04-04

