Skip to content

00 · 准备与安全

课程同时包含静态网站和本机 Python 练习。两者不是同一个运行环境:网页部署在公开地址,用户浏览器加载 HTML、CSS 和 JavaScript;Python 脚本则在你自己的电脑上运行,权限取决于当前操作系统用户和程序代码。公开网站可以展示教程,也可以执行页面 JavaScript,但不能因此读取你的仓库、启动本机 Python,或替你连接本机 MCP stdio Server。

仓库目前是 Private。网站访客可以访问已经构建并发布的静态页面,但不能通过公开网站下载这个 GitHub 仓库,也不能因此取得 lessons/ 下的源文件。若你没有仓库权限,可以阅读公开教程;要运行配套 Python 代码,需要获得仓库访问权限并克隆仓库。网站可见不等于源仓库公开,也不代表推送代码后网站会自动更新;当前发布方式是手动上传构建产物。

一次真实的模型请求还涉及第三个边界:模型供应商。你的应用会把请求消息、工具描述和必要的工具结果发给配置的服务。浏览器实验是直接从浏览器向 DeepSeek 发 HTTP 请求;本机脚本则通过 Python 客户端访问配置的 OpenAI 兼容服务。把资料交给模型前,先判断它能否离开你的设备。

仓库要求 Python 3.11 或更新版本,推荐用 uv 管理依赖。在仓库根目录执行:

Terminal window
python --version
uv sync

第一条命令应显示 Python 3.11.x 或更新版本;第二条会安装项目所需依赖。根项目依赖 OpenAI Python 客户端。LangChain 等后续练习使用可选依赖,稍后可以一次安装:

Terminal window
uv sync --extra exercises

这一步只准备本地环境,不会调用模型。第一课脚本需要供应商凭证和模型名称,二者从环境变量读取。不要把真实 Key 写进源码、命令历史、URL、聊天记录或截图。Key 由你在自己的终端中设置;下面的字符串只是占位符,不要原样运行:

Terminal window
export OPENAI_API_KEY='在本机终端设置你的凭证'
export OPENAI_MODEL='供应商支持的模型名称'
# 仅使用非默认 OpenAI 兼容端点时设置:
export OPENAI_BASE_URL='https://example.com/v1'
uv run python lessons/01_agent_loop/main.py '计算 (17 * 23) + 9'

脚本检查 OPENAI_API_KEY 和 OPENAI_MODEL 后才创建客户端并发请求。它会消耗供应商额度,具体费用取决于模型、请求和响应。示例提示的计算结果是 400;终端还会把每轮模型请求、工具调用和截断后的工具结果写到标准错误,最终回答写到标准输出。实际措辞和日志顺序由模型响应决定,因此不要把某一段自然语言答案当作固定输出。

如果你只想先读代码,完全可以暂不配置 Key。网站静态构建也不需要模型 Key;阅读页面、构建网站和调用模型是三件不同的事。

BYOK 指用户自行提供供应商凭证。单元 01 的浏览器实验有两种操作:无 Key 的确定性演示,以及输入 Key 后的实时请求。实时路径将页面中的 Key 放在发往 DeepSeek 的授权请求头中;React 组件把 Key 放在页面内存状态,不主动写入浏览器存储,也提供清除按钮。但在浏览器中,页面脚本能访问这段状态,因此“只在内存”不等于密钥对页面 JavaScript 保密。不要在公用电脑使用实时模式;使用额度较小、可撤销的凭证,练习结束后清除并按需在供应商控制台撤销。

本实验组件没有加入分析或第三方脚本,这降低了额外暴露面,不能消除浏览器、浏览器扩展、供应商端或其他页面代码带来的风险。不要把 Key 粘贴到聊天里,也不要把它加入 Git。教程不会要求你把凭证发给助教或模型。若不愿在浏览器使用 BYOK,选择“Show deterministic no-key trace”,或在自己的终端运行本机脚本。

终端也需要谨慎:export OPENAI_API_KEY=... 会让当前 Shell 进程及其子进程读取凭证,某些系统配置还可能保存命令历史。避免在录屏、共享终端或日志中展示真实值。课程仓库的 .gitignore 忽略 .env 文件,但忽略规则不是密钥管理系统;提交前仍应检查变更。

操作 执行位置 会否访问模型 需要留意
阅读课程页面 浏览器 否 静态页面内容来自网站
查看确定性 Tool Calling trace 浏览器 JavaScript 否 请求和结果由固定代码生成,不是模型回答
运行浏览器实时实验 浏览器 JavaScript 是 Key 和提示发送至 DeepSeek,可能产生费用
运行 lessons/01_agent_loop/main.py 本机 Python 是 请求发往终端环境中配置的供应商
启动本机 MCP stdio Server 本机进程 不一定 需要本地 MCP Client 实际启动并连接进程

网页上的“工具”只是页面中执行的 JavaScript 函数。它既不会继承本机 Python 的文件权限,也不会因为浏览器展示了某个 MCP Server 名称就真的启动该进程。判断实时请求是否发生,应检查实验明确显示的运行模式、浏览器网络请求或脚本执行日志;不要只凭“连接成功”这类文字下结论。

  • uv: command not found:本机尚未安装 uv,或安装目录不在 PATH。先完成 uv 安装并重开终端,再运行 uv --version。
  • Set OPENAI_API_KEY and OPENAI_MODEL...:当前终端没有这两个变量。确认在同一个终端会话中设置;新开终端不会自动继承旧会话的临时变量。
  • HTTP 401 或认证错误:检查 Key 是否有效、是否属于目标供应商。不要把 Key 发给别人来“代查”。
  • 找不到模型或 404:确认 OPENAI_MODEL 与端点支持的模型名称一致;使用兼容服务时检查 OPENAI_BASE_URL 是否为 API 根地址。
  • 超时、连接失败或 CORS 报错:确认网络和供应商可用。浏览器直连还受供应商 CORS 策略限制;本机 CLI 能访问不保证浏览器也能访问。
  • 仓库路径相关的读取失败:确认命令从仓库克隆目录运行,并使用仓库内相对路径。不要据此推断脚本可以任意读取整个电脑。

错误信息可能包含请求元数据。分享日志前检查并删除凭证、私人提示和文件内容。

  1. 运行 python --version,记录解释器版本;运行 uv sync,确认命令正常结束。**完成标准:**你能指出项目要求是 Python 3.11+,并说明依赖安装不会自行请求模型。
  2. 不设置 API Key,先打开 lessons/01_agent_loop/main.py,找到读取 OPENAI_API_KEY 的代码。**完成标准:**你能指出请求在哪一处发出,并区分“看代码”和“运行请求”。
  3. 对照上表,把一个浏览器确定性 trace、一条本机 Python 命令、一次模型供应商请求分别写入正确的执行位置。**完成标准:**三者不再被统称为“网站在运行 Agent”。
  4. 若有权限,可按 README 在本地设置凭证并运行 uv run python lessons/01_agent_loop/main.py '计算 12 * 9'。**完成标准:**日志显示至少一轮模型请求;算式的准确结果是 108,检查最终回答是否正确。模型不一定选择调用工具;不保存或分享凭证。若没有 Key 或仓库权限,完成前 3 项即可,不需要索取别人的凭证。

问:静态部署是否能保护浏览器中的 API Key?

不能。静态部署描述文件如何发布,不限制已下载到浏览器的 JavaScript。实时实验的 Key 会被页面代码读取并放入供应商请求,因此应视为该页面运行期间对脚本可见。内存态和清除按钮减少持久保存时间,但不能提供服务端密钥隔离。

问:网页能否直接运行本机 Python 或 MCP stdio 服务?

普通静态网页不能直接启动任意本机进程,也没有仓库文件系统权限。浏览器能执行页面 JavaScript;本机 Python/MCP 需要用户在本机启动程序并建立明确的通信通道。

问:如何确认一次演示有没有请求模型?

查看演示模式说明和实现。单元 01 的确定性模式调用 makeDemoTrace(),用固定消息、预设工具事件和本地函数生成 trace,不调用供应商;实时模式才调用 runToolCalling() 并向 api.deepseek.com 发请求。本地 Python 路线则从终端日志和实际供应商请求确认。