ai-agents-for-beginners

使用 Microsoft Foundry Local 和 Qwen 创建本地 AI 代理

创建本地 AI 代理

上一课将代理扩展到了云端。本课则将它们带回到单机上。完成后,你将拥有一个能推理、调用工具、读取文件、搜索文档的工作中的工程助手——无需任何云端推理调用。

为什么要这样做?真实工程工作中经常遇到三个原因:

代价是你以 CPU、GPU 或 NPU 上运行的小型语言模型 (SLM) 取代前沿的云端大模型。本课重点是构建在这个限制下表现良好的代理,而不是假装限制不存在。

简介

本课内容包括:

学习目标

完成本课后,你将能够:

前置条件

本课假设你已经完成之前的课程,熟悉:

你还需要:

小型语言模型:本地工作的正确工具

一个前沿云端模型有数千亿参数和数据中心支撑。SLM 有几个亿参数,必须适配你笔记本的内存。这个差异带来明确的预期。

SLM 擅长:

SLM 不擅长:

因此,本地代理的制胜策略是:让 SLM 负责编排,工具负责繁重工作。 模型不需要你的代码库——它需要知道何时调用 read_filesearch_docs。这正是 SLM 的优势所在。

flowchart LR
    U[开发者] --> A[本地 SLM 代理]
    A -->|决定使用哪个工具| T1[读取文件]
    A -->|决定使用哪个工具| T2[搜索文档 RAG]
    A -->|决定使用哪个工具| T3[分析代码]
    T1 --> A
    T2 --> A
    T3 --> A
    A --> R[回答,完全在设备上]

Microsoft Foundry Local

Microsoft Foundry Local 是一个轻量级运行时,能在你机器上完全下载、管理和服务模型。对我们最重要的功能是它暴露了兼容 OpenAI 的 HTTP 端点——这意味着 OpenAI SDK 和 Microsoft 代理框架的 OpenAI 客户端只需更改 base_url 即可对接。你关于构建代理学到的一切都能直接迁移;唯一变化是端点从云变成了 localhost

Foundry Local 还能自动为你的硬件选择最佳模型构建——CPU 构建、CUDA/GPU 构建或 NPU 构建——无需你为每台机器手动优化。

安装

安装 Foundry Local(见你的操作系统的文档),然后确认其功能正常:

# 安装(示例;请参考您的平台文档)
winget install Microsoft.FoundryLocal      # Windows
# brew install microsoft/foundrylocal/foundrylocal   # macOS

# 下载并运行Qwen模型,然后启动本地服务
foundry model run qwen2.5-7b-instruct
foundry service status

服务启动后,你就拥有了本地的兼容 OpenAI 端点(通常是 http://localhost:PORT/v1)。笔记本使用 foundry-local-sdk 自动发现端点,无需硬编码端口。

Qwen 函数调用:重要性所在

代理只有能调用工具才是真正的代理。许多 SLM 可以聊天,但无法可靠生成标准格式的工具调用。Qwen 模型专门训练用于函数调用,稳定输出格式良好的工具调用结构——这正是让本地聊天模型成为本地代理的关键。

流程是你熟悉的标准工具调用循环,只是运行在设备上:

sequenceDiagram
    participant U as 用户
    participant A as Qwen 代理(本地)
    participant T as 本地工具
    U->>A: "auth.py 做什么?"
    A->>A: 决定:调用 read_file
    A->>T: read_file("auth.py")
    T-->>A: 文件内容
    A->>A: 基于内容进行推理
    A-->>U: 解释

本地 RAG

文档检索是本地代理的立足之地。不是指望 SLM 记住框架文档,而是把文档嵌入到本地向量数据库,让代理按需检索相关片段。

我们使用 Chroma,它是一个嵌入式向量库,运行在进程内,无需服务器管理。数据流完全本地:本地嵌入模型 → 本地向量 → 本地检索 → 本地 SLM。

flowchart TB
    D[你的文档 / 代码] --> E[本地嵌入模型]
    E --> V[(Chroma 向量数据库 - 存储在磁盘上)]
    Q[代理查询] --> QE[本地嵌入查询]
    QE --> V
    V -->|前k块| A[Qwen 代理]
    A --> Ans[有根据的答案]

这与第5课的 Agentic RAG 模式相同——唯一变化是各组件都运行在你机器上。

本地 MCP 服务器

MCP 是一种传输协议,不是云服务。MCP 服务器可以作为本地进程运行于 stdio,通过标准协议向代理暴露工具。这让你可以离线复用日益丰富的 MCP 服务器生态——文件系统访问、git 操作、数据库查询等。

本地的安全策略不同于云端,但并非不存在:本地 MCP 服务器仍以你的用户权限运行,因此应限制其访问范围(项目目录,而非整个家目录)并将其输出视为输入,进行验证。

混合云+本地模式

本地优先不等于只能本地。成熟系统会根据敏感程度和难度分流:

场景 运行位置
敏感代码/数据,或离线时 本地 SLM
简单、有边界的任务 本地 SLM(廉价、快速)
非敏感数据的复杂多跳推理 云端模型
故障期间 本地 SLM(优雅降级)

这映射了第16课的模型路由理念——区别在于“模型”之一是你的本地机器。健壮设计是云不可用时回退到本地,让代理质量下降而非完全失败。

flowchart LR
    Q[请求] --> S{是否敏感或离线?}
    S -->|是| L[本地 SLM]
    S -->|否| C{需要深度推理吗?}
    C -->|否| L
    C -->|是| Cloud[云模型]
    L --> Out[响应]
    Cloud --> Out

实操实验:本地工程助理

打开 code_samples/17-local-agent-foundry-local.ipynb 并完成实验。你将构建一个完全运行在工作站上的本地工程助理,能够:

  1. 工具调用——通过 Foundry Local 使用 Qwen 函数调用。
  2. 本地文件操作——列出和读取项目目录文件。
  3. 代码分析——对源文件报告基本指标。
  4. 文档搜索——使用 Chroma 在本地文档文件夹上进行 RAG。
  5. 使用 MCP——连接到本地 MCP 服务器(未配置时优雅跳过)。

期间完全不使用云端推理。

解析指导

助理通过兼容 OpenAI 的端点连接 Foundry Local,代理代码几乎和云端课程完全一致——唯一变化是客户端:

from foundry_local import FoundryLocalManager
from openai import OpenAI

# Foundry Local 发现/下载模型并为我们提供本地端点。
manager = FoundryLocalManager(\"qwen2.5-7b-instruct\")
client = OpenAI(base_url=manager.endpoint, api_key=manager.api_key)  # api_key 是本地占位符

工具是普通的 Python 函数,限制在项目目录内:

def read_file(path: str) -> str:
    \"\"\"Read a file, but only inside the sandboxed project directory.\"\"\"
    full = (PROJECT_ROOT / path).resolve()
    if PROJECT_ROOT not in full.parents and full != PROJECT_ROOT:
        return \"Access denied: path is outside the project directory.\"
    return full.read_text(encoding=\"utf-8\")

注意沙箱检查——即使本地,读取任意路径的工具也是风险。笔记本将所有工具均限定在单一项目根目录。

知识检测

在做作业前测试你的理解。

1. 给出在本地运行代理而非云端的两个具体理由。

答案 任选两项:隐私(代码和数据永远不离机)、成本(无每 token 推理计费)和离线能力(无网络也能工作,如飞机、保密设施或停电时)。法律/合规限制禁止传输数据设备外,往往是隐私驱动的主要原因。

2. SLM 与其工具在本地代理中的推荐分工是什么,为什么?

答案 让 SLM 负责编排(决定调用哪个工具及参数),让工具负责繁重工作(读文件、取文档、计算结果)。SLM 擅长有限决策如工具选择,不擅长广泛知识和长多步推理,因此依赖工具发挥优势。

3. 是什么使我们能用 Foundry Local 复用云端代理代码?

答案 Foundry Local 暴露了兼容 OpenAI 的 HTTP 端点。OpenAI SDK 和代理框架的 OpenAI 客户端只需修改 `base_url`(并用本地占位 API key)便可使用。代理代码其他部分保持不变。

4. 为什么具体使用 Qwen 函数调用模型,而非任意 SLM?

答案 因为代理必须生成可靠且格式良好的工具调用。许多 SLM 可聊天,但产生格式错误或不一致的工具调用。Qwen 模型专注函数调用训练,产出一致的工具调用,是本地聊天模型变工作代理的关键。

5. 在本地 RAG 流程中,哪些组件运行在机器上?

答案 全部:嵌入模型、向量数据库(磁盘上的 Chroma)、检索步骤和 SLM。文档本地嵌入、本地存储、本地检索、本地模型推理——无组件接触云端。

6. 本地 MCP 服务器运行在你机器上,这是否自动意味着它安全?还需采取什么预防措施?

答案 不是。它以你的用户权限运行,因此能访问你能访问的一切。应限制其范围(如仅限某项目目录,而非整个家目录),并将其输出视为输入,验证后再操作。

7. 描述包含本地模型的合理混合路由规则。

答案 将敏感或离线请求路由到本地 SLM;将简单有边界任务路由到本地 SLM(快速、廉价);将非敏感数据上的复杂多跳推理路由到云模型;云不可用时回退本地 SLM,使代理优雅降级而非失败。这是第16课模型路由思想,本地机器作为其中一个模型。

8. 本课本地代理运行的实际最低内存需求是多少?更多内存带来什么?

答案 实际最低约 **8 GB**;16 GB 以上更舒适。更多内存允许运行更大更强模型,保持更多上下文。GPU 或 NPU 加速推理,但非必须——无加速时 Foundry Local 选择 CPU 版本。

作业

将本地工程助理扩展成一个你选小项目的本地文档审阅器(可用本仓库的任一课程文件夹)。

你的提交应包含:

  1. 把真实的文档/代码文件夹索引入 Chroma(至少五个文件)。
  2. 添加一个 find_todos 工具,扫描项目中的 TODO/FIXME 注释并返回文件和行号——保持与 read_file 一样的沙箱检查。

  3. 向代理提三个问题,迫使它结合使用工具:一个纯RAG问题,一个需要阅读特定文件的问题,以及一个需要查找TODO的问题。
  4. 测量它:记录三个回答的时间,并在markdown单元中注明。评论延迟是否符合您预期的工作流程。

然后写一段简短的文字,说明您会将哪些内容迁移到云端,哪些内容保留在本地,以及原因。评估重点是本地组件是否正确连接,以及混合推理是否合理——而非模型质量。

总结

在本课中,您构建了一个完全在自己电脑上运行的代理:

这完成了部署过程:第16课将代理扩展到了Microsoft Foundry,本课则将它们缩减到了单个工作站。下一课将聚焦于保持已经部署代理的安全。

附加资源

上一课

部署可扩展代理

下一课

保障AI代理安全


免责声明: 本文件由 AI 翻译服务 Co-op Translator 翻译完成。尽管我们力求准确,但请注意,自动翻译可能包含错误或不准确之处。原始语言版文件应视为权威来源。对于重要信息,建议使用专业人工翻译。我们对因使用本翻译而产生的任何误解或误释不承担责任。