本地大模型落地实战教程:从 0 搭一个私有 AI 工作台

> 来源文章:KDnuggets《5 Cool Things I Did with Local Language Models》 > 原文链接:https://www.kdnuggets.com/5-cool-things-i-did-with-local-language-models > 本文定位:基于原文 5 个案例,重写成可照做的落地教程。重点不是“本地模型很好”,而是给出具体场景、目录、命令、Prompt、验收标准和失败处理。

0. 你最终会得到什么

完成本文后,你会得到一个本地 AI 工作台,包含 4 个可用场景:

1. 私有文档问答库:把合同、PDF、项目笔记放进本地 RAG,问问题时引用来源。 2. 本地代码审查助手:用 Qwen2.5-Coder 审查敏感代码,不上传到云端。 3. 固定风格个人助手:用 Modelfile 固化你的输出偏好和工作背景。 4. 最小只读 Agent:读取本地日志或文本,生成报告,默认不改原文件、不碰生产系统。

建议按顺序做,不要一上来做 Agent。

Ollama 跑通
  ↓
文档问答库
  ↓
代码审查助手
  ↓
个人助手 Modelfile
  ↓
只读 Agent 原型

1. 前置准备

1.1 推荐机器配置

最低可试:

更舒服:

1.2 安装 Ollama

去官网下载并安装:

https://ollama.com

验证:

ollama --version

启动服务:

ollama serve

如果提示端口已占用,通常说明 Ollama 已经在后台运行。

1.3 拉取基础模型

ollama pull llama3.2:3b
ollama pull mistral:7b
ollama pull qwen2.5-coder:7b

验证模型可用:

ollama run llama3.2:3b

输入:

请用一句话解释什么是本地大模型。

验收:能正常返回中文回答即可。

2. 案例一:搭一个私有文档问答库

2.1 目标

把本地文档放进一个私有知识库,能回答:

关键要求:文档不上传云端,回答必须引用来源。

2.2 建一个测试资料目录

先不要导入所有真实文档。先建一个小样本,方便验证系统是否靠谱。

mkdir -p ~/local-ai-workbench/docs-sample
cd ~/local-ai-workbench/docs-sample

创建两份示例制度:

cat > policy-2023.md <<'EOF'
# 客户数据保留政策 2023

客户订单数据保留 3 年。
客户聊天记录保留 180 天。
超过保留周期后,应在 30 天内删除或匿名化。
EOF

cat > policy-2025.md <<'EOF'
# 客户数据保留政策 2025

客户订单数据保留 5 年。
客户聊天记录保留 90 天。
高风险客户数据需要单独加密存储。
超过保留周期后,应在 15 天内删除或匿名化。
EOF

这两份文件故意设计了冲突点:订单数据从 3 年变 5 年,聊天记录从 180 天变 90 天,删除窗口从 30 天变 15 天。

2.3 启动 AnythingLLM

docker run -d \
  --name anythingllm \
  -p 3001:3001 \
  -v anythingllm_storage:/app/server/storage \
  mintplexlabs/anythingllm

打开:

http://localhost:3001

在 AnythingLLM 中:

1. 新建 Workspace:private-docs-test 2. LLM Provider 选择 Ollama 3. Ollama 地址填:http://localhost:11434 4. 模型选择:llama3.2:3bmistral:7b 5. 上传 policy-2023.mdpolicy-2025.md

2.4 用具体问题验收,不要泛泛聊天

不要问:

帮我总结这些文档。

要问这种能验证检索质量的问题:

请对比 policy-2023.md 和 policy-2025.md 的客户数据保留政策。
必须输出:
1. 两份文件一致的地方
2. 两份文件冲突的地方
3. 每个结论引用来源文件名
4. 如果文档没有提到,不要猜

理想回答应包含类似内容:

冲突点:
- 订单数据保留周期:2023 文件为 3 年,2025 文件为 5 年。
- 聊天记录保留周期:2023 文件为 180 天,2025 文件为 90 天。
- 删除/匿名化窗口:2023 文件为 30 天内,2025 文件为 15 天内。

新增要求:
- 2025 文件新增“高风险客户数据需要单独加密存储”。

2.5 判断是否可以导入真实文档

通过这 5 条再导入真实资料:

如果做不到,先换 mistral:7b,再检查文档切块和 embedding 配置,不要急着导入几百份文档。

3. 案例二:本地代码审查助手

3.1 目标

用本地模型审查公司代码或个人项目代码,避免把代码粘到云端 AI。

适合审查:

不适合第一轮审查:

3.2 准备一个故意有问题的函数

mkdir -p ~/local-ai-workbench/code-review-demo
cd ~/local-ai-workbench/code-review-demo

cat > user_api.py <<'EOF'
def get_user_data(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"
    result = db.execute(query)
    return result.fetchone()
EOF

这个函数有 3 个典型问题:

1. SQL 注入风险 2. SELECT * 可能暴露多余字段 3. 用户不存在时返回 None,调用方可能在更远处报错

3.3 用 Qwen2.5-Coder 审查

启动模型:

ollama run qwen2.5-coder:7b

输入下面这个审查 Prompt:

你是一名资深软件工程师,正在做代码审查。
你的任务是找问题,不要鼓励我。

审查重点:
1. 安全漏洞:SQL 注入、鉴权、数据泄露
2. 边界条件:空值、异常、不存在的数据
3. 复杂度:是否有不必要的写法
4. 真实环境会失败的假设

输出格式:
- 问题:
- 风险:
- 为什么是问题:
- 建议修改:

不要复述代码功能,直接输出发现的问题。

代码如下:

def get_user_data(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"
    result = db.execute(query)
    return result.fetchone()

3.4 你应该期待什么结果

合格的模型输出应该指出:

问题 1:SQL 注入
风险:user_id 直接拼进 SQL,攻击者可构造输入改变查询语义。
建议:使用参数化查询。

问题 2:SELECT * 数据暴露
风险:返回不需要的敏感字段,例如 password_hash、token、internal_note。
建议:只选择必要字段。

问题 3:空结果未处理
风险:用户不存在时返回 None,调用方可能出现 NoneType 错误。
建议:显式处理未找到场景,返回错误或抛出业务异常。

3.5 给它一个修复目标

继续输入:

请基于上面的审查结果,给出一个更安全的 Python 版本。
约束:
1. 使用参数化查询
2. 不要 SELECT *
3. 用户不存在时显式返回 None,并在注释里提醒调用方处理
4. 不要引入新依赖

参考修复:

def get_user_data(db, user_id: int):
    query = """
    SELECT id, name, email
    FROM users
    WHERE id = ?
    """
    result = db.execute(query, (user_id,))
    row = result.fetchone()
    if row is None:
        return None
    return row

注意:不同数据库驱动的占位符不一样。SQLite 常用 ?,PostgreSQL 常见 %s$1,SQLAlchemy 又是另一套写法。模型给的修复必须按你的实际技术栈二次确认。

3.6 接入 IDE 的最小配置

如果使用 Continue,配置本地模型:

{
  "models": [
    {
      "title": "Qwen2.5-Coder Local",
      "provider": "ollama",
      "model": "qwen2.5-coder:7b",
      "apiBase": "http://localhost:11434"
    }
  ]
}

第一周只让它审查单文件或选中代码块,不要让它自动改整个项目。

3.7 代码审查验收标准

4. 案例三:离线个人助手

4.1 目标

提前把模型下载到本地,在断网场景下处理写作、计划、复盘、草稿等任务。

4.2 出差/飞行前准备

ollama pull mistral:7b
ollama list

确认列表里有 mistral:7b

断网测试:

1. 关闭 Wi-Fi 2. 运行:

ollama run mistral:7b

3. 输入:

我现在离线。请只基于我提供的信息回答。
我要写一封邮件,目标是把项目延期 3 天的原因说清楚,但不要甩锅。背景如下:
- 接口联调比预期多花 2 天
- 测试环境昨天不可用半天
- 我们已经补了回归测试
请给我一版简洁邮件草稿。

4.3 离线助手的正确用法

适合:

不适合:

4.4 离线 Prompt 模板

我现在处于离线环境。
你只能基于我提供的材料回答。
如果材料不足,请明确说“材料不足,无法判断”。
不要补充外部事实。

任务:
[写清楚你要它做什么]

材料:
[粘贴本地材料]

输出格式:
1. 结论
2. 草稿/步骤
3. 需要联网后再核验的点

4.5 验收标准

5. 案例四:用 Modelfile 固化你的工作偏好

5.1 目标

把每次都要重复说的背景写进本地模型:语言、风格、工作角色、输出格式、禁忌。

5.2 创建个人助手

mkdir -p ~/local-ai-workbench/my-assistant
cd ~/local-ai-workbench/my-assistant

写入 Modelfile

cat > Modelfile <<'EOF'
FROM llama3.2:3b

SYSTEM """
你是我的本地工作助手。

关于我:
- 我主要做工程实践、自动化脚本、技术文章整理。
- 我偏好中文回答。
- 我不喜欢空泛建议。

工作方式:
- 先给结论,再给步骤。
- 如果请求含糊,先改写成更清楚的问题,再回答。
- 优先给最简单够用的方案,不要过度工程化。
- 不确定就说不确定,不要编造。

输出格式:
1. 结论
2. 具体步骤
3. 验证方式
4. 风险或限制
"""

PARAMETER temperature 0.4
PARAMETER num_ctx 4096
EOF

创建模型:

ollama create my-work-assistant -f Modelfile
ollama run my-work-assistant

5.3 对比测试

输入:

我想把一篇技术文章转成内部分享稿,请给我一个 30 分钟内能完成的流程。

合格输出应该类似:

结论:30 分钟内不要追求完整复刻原文,应提炼成“问题-方案-演示-边界”的分享结构。

具体步骤:
1. 5 分钟:提取文章一句话结论和 3 个关键案例。
2. 10 分钟:改成内部听众关心的落地场景。
3. 10 分钟:补一个可运行 Demo 或截图。
4. 5 分钟:写风险边界和下一步试点。

验证方式:让一个同事只看标题和步骤,判断是否知道怎么试。

如果模型仍然输出很多泛泛建议,就回到 Modelfile 里继续收紧要求。

6. 案例五:做一个只读本地 Agent

6.1 目标

让模型读取本地文件,生成报告。第一版不联网、不删除文件、不覆盖原始数据。

这个案例比原文的“搜索 + 写文件 Agent”更保守,适合作为第一版落地。

6.2 准备目录和样本日志

mkdir -p ~/local-ai-workbench/read-only-agent/{input,output}
cd ~/local-ai-workbench/read-only-agent

cat > input/app.log <<'EOF'
2026-05-19 09:00:01 INFO service started
2026-05-19 09:02:11 WARN retry payment callback order_id=1001
2026-05-19 09:03:42 ERROR database timeout query=get_user order_id=1002
2026-05-19 09:05:10 INFO payment callback success order_id=1001
2026-05-19 09:06:55 ERROR failed to send webhook order_id=1003
EOF

6.3 写一个只读分析脚本

这个脚本使用 Ollama 原生 HTTP API,只依赖 Python 标准库。

cat > local_log_agent.py <<'EOF'
import json
from pathlib import Path
from urllib.request import Request, urlopen

ROOT = Path(__file__).parent.resolve()
INPUT = ROOT / "input" / "app.log"
OUTPUT_DIR = ROOT / "output"
OUTPUT = OUTPUT_DIR / "log_report.md"
MODEL = "llama3.2:3b"

SYSTEM_PROMPT = """
你是一个只读日志分析助手。
约束:
1. 只能基于用户提供的日志内容分析。
2. 不要编造日志里没有的信息。
3. 输出中文 Markdown。
4. 必须包含:错误摘要、告警摘要、可能影响、建议排查顺序。
"""


def call_ollama(prompt: str) -> str:
    payload = {
        "model": MODEL,
        "messages": [
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": prompt},
        ],
        "stream": False,
    }
    req = Request(
        "http://localhost:11434/api/chat",
        data=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urlopen(req, timeout=120) as response:
        data = json.loads(response.read().decode("utf-8"))
    return data["message"]["content"]


def main() -> None:
    if not INPUT.exists():
        raise SystemExit(f"missing input file: {INPUT}")

    log_text = INPUT.read_text(encoding="utf-8")
    prompt = f"请分析以下日志:\n\n{log_text}"
    report = call_ollama(prompt)

    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    OUTPUT.write_text(report + "\n", encoding="utf-8")
    print(f"written: {OUTPUT}")


if __name__ == "__main__":
    main()
EOF

6.4 运行

确保 Ollama 服务在运行:

ollama serve

另一个终端运行:

python3 local_log_agent.py

查看输出:

cat output/log_report.md

6.5 你应该看到什么

合格报告应包含:

错误摘要:
- database timeout 出现在 get_user 查询,关联 order_id=1002。
- failed to send webhook,关联 order_id=1003。

告警摘要:
- payment callback 对 order_id=1001 出现 retry,随后成功。

建议排查顺序:
1. 先查数据库超时是否影响 get_user 查询链路。
2. 再查 webhook 发送失败的目标服务和重试机制。
3. 最后确认 order_id=1001 是否已最终一致。

6.6 为什么这是 Agent,而不是普通总结

因为它已经具备最小闭环:

读取本地输入 → 调用本地模型 → 生成本地报告 → 保留可审计文件

但它还不是全自动运维 Agent。它没有权限删除、重启、部署、发消息。这是有意为之。

6.7 第一版安全边界

必须保留:

如果后续要加“搜索目录”“读取多个文件”,也只扩大读取范围,不扩大写入或执行权限。

7. 一周落地计划

第 1 天:跑通模型

任务:

ollama pull llama3.2:3b
ollama run llama3.2:3b

验收:模型能稳定中文回答。

第 2 天:文档问答小样本

任务:用 policy-2023.mdpolicy-2025.md 验证 AnythingLLM。

验收:能指出 3 个冲突点,并引用来源。

第 3 天:代码审查小样本

任务:审查 get_user_data() 示例函数,再换成你自己的一个低风险函数。

验收:能发现真实问题,建议不脱离你的技术栈。

第 4 天:个人助手

任务:创建 my-work-assistant

验收:默认中文、直接、能先改写含糊问题。

第 5 天:只读 Agent

任务:跑通 local_log_agent.py

验收:生成 output/log_report.md,且不改动 input/app.log

第 6 天:换成真实低风险材料

任务:

验收:每个场景都能产生一个可检查的输出。

第 7 天:决定是否继续投入

只问 4 个问题:

1. 它是否减少了重复劳动? 2. 它是否保护了不能上传云端的数据? 3. 它是否能被验证,而不是只靠感觉? 4. 它是否没有扩大权限风险?

如果答案不明确,继续小样本,不要急着接入生产流程。

8. 三个可直接分享的演示脚本

演示 1:隐私文档不会离开本机

演示流程:

1. 展示两份本地 Markdown 政策文件。 2. 上传到 AnythingLLM。 3. 提问“找出冲突点并引用来源”。 4. 关闭网络后再次提问简单问题。 5. 强调:文档在本地,模型在本地,回答可追溯。

演示 2:代码审查发现 SQL 注入

演示流程:

1. 展示 get_user_data()。 2. 用 Qwen2.5-Coder 审查。 3. 让模型指出 SQL 注入、SELECT *、空结果处理。 4. 展示修复版。 5. 强调:不要让模型直接改全仓库,先审小片段。

演示 3:只读日志 Agent 生成报告

演示流程:

1. 展示 input/app.log。 2. 运行 python3 local_log_agent.py。 3. 展示 output/log_report.md。 4. 强调:第一版只读、固定输出目录、可审计。

9. 常见失败和处理方法

9.1 模型太慢

处理:

9.2 文档问答乱引用

处理:

9.3 代码审查建议不适配项目

处理:

9.4 Agent 想做危险操作

处理:

10. 最小落地检查表

环境

文档问答

代码审查

个人助手

只读 Agent

11. 分享时的主线

开场可以这样说:

> 本地大模型不是为了替代最强云模型,而是为了解决云模型天然不适合的场景:隐私、离线、低成本、高频试错和本地工具接入。

中间用 3 个案例支撑:

1. 私有文档问答:文档不动,AI 来读。 2. 本地代码审查:代码不上传,先发现低级风险。 3. 只读 Agent:先做可审计的小闭环,再谈自动化。

收尾可以这样说:

> 本地 AI 落地的关键不是模型参数,而是边界:输入是什么、允许做什么、输出在哪里、怎么验证。边界清楚,小模型也能产生实际价值;边界不清楚,大模型也会放大风险。

12. 本文和原文的关系

原文提供了 5 个实践灵感:私有文档脑、代码审查、离线助手、个人思考伙伴、本地 Agent。本文把它改造成可执行教程,并额外补充了样本文件、审查代码、只读 Agent 脚本、一周计划和验收清单。

原文里的能力边界仍然成立:本地 3B/7B 模型不适合替代前沿云模型做复杂推理。它更适合在边界清楚、风险可控、数据需要留在本地的场景里先落地。