实验 04 · OpenCode + Python
OpenCode 与 Python 小项目
用熟悉的 Python 列表计算平均值、平方、平方和和中心化值。
完整讲义
实验 4:OpenCode 与 Python 小项目
目标
理解大型语言模型(LLM)、Agent 和 OpenCode 之间的关系,然后在一个小型 Python 项目中 使用 OpenCode,继续复用 PowerShell、VS Code 和实验笔记工作流。
本实验为实验 5 的 Python 阶段性小作业做准备。请认真记录命令、文件结构和人工检查, 因为下一次实验会复用这些工作流。
大型语言模型(LLM)是什么
大型语言模型,英文是 Large Language Model,简称 LLM。它可以根据输入生成文字或代码。
LLM 读取和生成信息的基本单位称为 token。一个 token 可能是一个汉字、一个词的一部分、 标点或代码符号。LLM 的基本原理可以简单理解为:根据已有内容预测下一个 token。
模型输出一个 token 后,会把这个 token 加入已有内容,再预测下一个 token。不断重复这个过程, 就会逐步形成一句话、一段代码或一个完整回答。
例如,面对下面这段尚未完成的代码:
numbers = [1, 2, 3]
total = 0
for number in numbers:
total =
模型可能预测接下来的内容是 total + number。随后它继续预测换行、下一条语句以及后面的 解释,直到回答结束。
模型预测时能够参考的信息称为上下文。它一次能够使用的上下文范围称为上下文窗口。 提示词、当前对话,以及外部程序提供的文件内容或运行结果都可以成为上下文;没有进入上下文 的信息不会被模型自动知道。
预测下一个 token 可以生成结构合理的解释和代码,但不保证内容一定正确。LLM 仍可能误解 问题、生成不存在的函数或给出错误计算,因此结果需要检查。
从 LLM 到工具
现在考虑一个具体要求:读取 labs/lab04/average.py,运行它,并根据真实输出检查代码。
只有 LLM 时,本地文件内容不在上下文中,模型无法知道文件实际写了什么。它可以生成一条 看起来正确的命令:
python labs\lab04\average.py
但这行命令仍然只是模型输出的 token。它没有因此进入 PowerShell,文件也没有因此被读取或 运行。生成文字不等于执行动作。
从语言生成跨到读取文件、修改代码和运行程序,需要另一个软件组件把明确的操作交给计算机 执行。这个能力边界自然引出了工具。
工具是什么
工具是围绕 LLM 运行的外部程序向模型提供的一项可调用能力。读取硬盘中的文件、修改代码 或启动 Python 都由工具实际完成;模型负责判断何时需要这项能力,并提供调用所需的信息。
一个工具通常需要说明:
- 工具名称:如何识别这个能力;
- 用途:它可以完成什么操作;
- 输入参数:执行操作需要哪些信息;
- 返回结果:操作完成后把什么信息交回模型。
| 工具示例 | 输入参数 | 返回结果 |
|---|---|---|
| 读取文件 | 文件路径 | 文件内容或读取错误 |
| 修改文件 | 文件路径和修改内容 | 修改是否完成 |
| 运行命令 | PowerShell 命令 | 命令输出、错误信息和结束状态 |
这里的“工具”不是一个模糊的智能能力,而是输入和输出都相对明确的程序接口。相同的工具可以 被多次调用,每次调用都应产生可供后续判断的结果。
LLM 如何调用工具
LLM 不会亲自按键、打开文件或启动 PowerShell。外部程序会把当前可用工具的名称、用途和 输入格式放入模型上下文。LLM 可以在需要行动时生成一个结构化的工具调用请求,而不是 只生成一段给人阅读的文字。
例如,当任务要求运行 Lab 4 的程序时,模型可以生成含有以下信息的请求:
工具名称:运行命令
输入参数:python labs\lab04\numbers_summary.py
一次完整调用包含以下步骤:
- 外部程序向 LLM 提供工具说明。
- LLM 根据任务和上下文生成工具名称与输入参数。
- 外部程序解析请求并执行对应工具。
- 工具返回文件内容、命令输出或错误信息。
- 外部程序把返回结果加入上下文,LLM 再决定下一步。
真正执行工具的是围绕 LLM 运行的外部程序。它读取调用请求,运行对应工具,再把返回结果加入 下一轮上下文:
LLM 生成工具调用请求
↓
外部程序执行对应工具
↓
工具返回程序输出或错误信息
↓
LLM 根据返回结果继续生成下一步
因此,“LLM 能调用工具”是一种简写。更准确地说,是 LLM 按工具说明生成调用请求,外部程序 负责执行,并把结果送回模型。这个连接让语言生成能够影响真实项目。
从 LLM 到 Agent
单独的 LLM 主要接收内容并生成内容。要让它围绕一个真实任务持续采取行动,还需要在模型 外部加入目标、工具和执行循环。这样的系统称为 Agent,也就是代理。可以先把它理解为:
Agent = LLM + 目标 + 工具 + 反馈循环
用户说明目标
↓
LLM 根据当前上下文提出下一步行动
↓
Agent 调用工具读取文件、修改文件或运行命令
↓
工具结果返回上下文
↓
LLM 根据新结果决定下一步行动
Agent 的关键不是“回答更长”,而是能够调用工具,并把工具结果带回下一轮判断。例如, 它可以先读取 Python 文件,再修改代码,随后运行程序,并根据错误信息继续修正。
Agent 能行动,不代表它可以独立判断任务是否真正完成。目标可能描述不清,工具可能返回 错误,模型也可能误解结果,因此仍然需要人工检查。
OpenCode 是什么
OpenCode 是面向软件项目的 coding agent。它从 PowerShell 启动,在当前项目中读取文件、 修改文件、运行命令,并把命令结果用于后续工作。
本课程还会同时出现两个名称:
- OpenCode Go 是 OpenCode 连接的模型提供商,负责提供模型访问;
- DeepSeek V4 Pro 是本课程选择的 LLM,完整模型标识为
opencode-go/deepseek-v4-pro。
因此,OpenCode、提供商和模型不是同一个对象。你在 OpenCode 中提出任务,OpenCode 把提示词、 文件内容和工具结果组织成上下文,DeepSeek V4 Pro 预测下一步回答或工具调用请求,再由 OpenCode 执行对应工具。
在本课程中,各工具承担不同职责:
- PowerShell 提供命令行环境;
- VS Code 用于查看和编辑项目;
- Python 或 MATLAB 真正执行程序;
- OpenCode 组织上下文,并执行文件读取、代码修改和命令运行等工具;
- OpenCode Go 为 OpenCode 提供模型访问;
- DeepSeek V4 Pro 根据上下文生成回答或工具调用请求。
启动 OpenCode 时所在的目录决定了它首先面对哪个项目。OpenCode 使用 LLM 理解你的要求,并通过 Agent 机制调用工具;它不会取代 Python、MATLAB,也不会取代你对数学结果的判断。
| 对象 | 主要作用 | 使用的信息 | 能否操作项目 |
|---|---|---|---|
| 单独的 LLM | 生成、解释或改写内容 | 当前上下文窗口 | 通常只生成内容 |
| Agent | 围绕目标循环调用工具 | 上下文与工具返回结果 | 可以通过工具操作 |
| OpenCode | 处理软件项目中的编程任务 | 提示词、项目文件与命令输出 | 可以通过工具读取、修改和运行 |
| OpenCode Go | 提供模型访问 | 账号、API Key 与模型列表 | 不直接操作项目 |
| DeepSeek V4 Pro | 预测回答或工具调用请求 | OpenCode 提供的上下文 | 不直接执行工具 |
OpenCode 的工作闭环
一次可靠的 OpenCode 工作通常不是“提问一次,然后结束”,而是一个循环:
你说明目标、上下文、约束和完成条件
↓
OpenCode 使用 LLM 理解任务并选择下一步行动
↓
OpenCode 通过 Agent 工具查看文件、修改代码或运行命令
↓
你检查改动、运行结果和数学含义
↓
你补充要求,OpenCode 根据新上下文继续处理
本实验会完整经历这个循环。后面的实验虽然任务更复杂,基本工作方式不变。
OpenCode 提供 Plan 模式和 Build 模式。本课程在 Plan 模式中先阅读项目、分析任务并 形成计划,确认后再切换到 Build 模式修改文件。两种模式都使用同一个项目上下文,但承担的 任务阶段不同。按 Tab 可以在两种模式之间切换,界面底部会显示当前模式。
概念检查
在开始编程前,先在 notes/lab04-notes.md 中用自己的话回答:
- LLM 如何通过预测下一个 token 生成完整回答?
- 为什么 LLM 生成一条 PowerShell 命令并不等于已经运行了它?
- 一次工具调用中,LLM 和外部程序分别负责什么?
- 为什么 OpenCode 运行结果仍需人工数学验证?
如何写清楚任务
不需要学习特殊的“提示词语法”,但重要任务最好说明以下四点:
| 部分 | 要回答的问题 | 本实验中的例子 |
|---|---|---|
| 目标 | 最终要得到什么? | 创建数据总结程序 |
| 上下文 | OpenCode 应查看哪些文件和数据? | labs/lab04/ 与给定列表 |
| 约束 | 哪些做法不合适? | 使用基础 Python,不安装第三方包 |
| 完成条件 | 怎样判断任务完成? | 程序能运行,且关键数值通过手算检查 |
这些信息不是越多越好。只写会改变结果或帮助验证结果的内容,通常比罗列大量操作步骤更有效。
数学任务
对列表:
[1, 2, 3, 4, 5]
计算:
- 平均值;
- 每个数的平方;
- 平方和;
- 中心化后的值,即每个值减去平均值。
小知识:.py 扩展名有什么作用?
.py 是一种约定,帮助 Windows、VS Code 和其他工具判断“这个文件可能包含 Python 源代码”。扩展名本身不会把任意文字变成程序:把错误内容保存为 .py,Python 仍会报错; 一段有效代码即使暂时写在 .txt 中,也仍然只是相同的字符。真正决定含义的是文件内容, 扩展名负责让工具更早选择合适的打开和处理方式。
目录结构
创建如下目录结构:
labs/lab04/
hello.py
average.py
numbers_summary.py
notes/
lab04-notes.md
如果课程根目录中还没有 starters/,先下载 Starter 文件, 并按照实验 2 的说明解压。
准备与运行
- 将
starters/lab04/中的 starter 文件复制到labs/lab04/。 - 在
notes/lab04-notes.md中记录实验过程。 - 运行 starter 文件:
python labs\lab04\hello.py
python labs\lab04\average.py
- 在 OpenCode 修改代码前记录 starter 状态:
git add labs\lab04 notes\lab04-notes.md
git commit -m "chore: prepare lab 4 starter"
git status
确认 git status 显示工作区干净。这样后面的差异只包含本次 OpenCode 任务产生的修改。
第一次启动与检查
从课程根目录启动 OpenCode:
opencode
OpenCode 启动后输入 /models,确认当前模型为 DeepSeek V4 Pro,完整标识为 opencode-go/deepseek-v4-pro:
/models
/models 是 OpenCode 内部命令,不是 PowerShell 命令。模型选择可能沿用上一次会话, 仍应在每次正式使用前确认,避免不同实验使用了不同模型。
按 Tab 切换到 Plan 模式。确认界面显示 Plan 后,遵循“先查看,不修改”的顺序, 输入一次只读检查提示词:
先查看 labs/lab04/ 中现有的 Python 文件,不要修改任何文件。
说明每个文件目前做什么,并告诉我完成本实验还缺少什么。
这一步把“理解现状”和“开始修改”分开。阅读 OpenCode 的回答,并确认它提到的是 hello.py、average.py 和缺少的 numbers_summary.py。
OpenCode 任务
完成只读检查并确认计划合理后,按 Tab 切换到 Build 模式,再输入实现提示词:
目标:在 labs/lab04 中创建 numbers_summary.py。
上下文:我具备基础 Python 知识。使用数据 [1, 2, 3, 4, 5]。
修改前先阅读 labs/lab04 中已有的文件。
约束:使用适合初学者阅读的 Python 和简短注释。不要安装第三方包,
不要修改 hello.py 或 average.py。
完成条件:程序输出平均值、平方列表、平方和以及中心化后的值。
运行一次程序,报告所用命令和输出;如果出现错误,解释错误原因。
OpenCode 完成修改后,保留当前会话,在 VS Code 中再打开一个 PowerShell 终端。运行:
git status
git diff -- labs\lab04
git status 显示哪些文件发生了变化;git diff -- labs\lab04 只显示 Lab 4 相对于最近一次 提交的逐行差异。重点确认数据列表没有被改动、计算公式符合题意,并且没有出现本实验不需要 的文件或第三方库。实验 3 创建了仓库基线,本实验又提交了 starter 状态,因此这里看到的是 从该检查点开始的变化。
然后输入解释提示词:
请逐行解释 numbers_summary.py。
重点说明平均值、平方、平方和与中心化值的数学含义,
并指出哪些结果需要我手算验证。
运行与检查
运行:
python labs\lab04\numbers_summary.py
手动检查:
- 平均值应为
3; - 平方应为
[1, 4, 9, 16, 25]; - 平方和应为
55; - 中心化后的值应为
[-2, -1, 0, 1, 2]; - 中心化后的值之和应为
0。
如果程序报错或结果不一致,不要立刻重新开始一个会话。把实际错误或不一致之处告诉 OpenCode:
我运行了 python labs\lab04\numbers_summary.py。
实际输出:[在这里粘贴相关输出或错误信息]
预期结果:[写出经过手算检查的值]
请找出原因,只做必要的最小修改,然后重新运行程序。
修正后在第二个 PowerShell 终端再次运行 git status 和 git diff -- labs\lab04。完成实验时, 可以在 OpenCode 中输入 /exit 返回 PowerShell。
验证结果后保存本次检查点:
git add labs\lab04 notes\lab04-notes.md
git commit -m "feat: complete lab 4"
git status
最后一次 git status 应再次显示工作区干净。后续实验会复用“先确认基线、完成任务、人工 验证、再提交检查点”的节奏,不再重复解释每条 Git 命令。
完成内容
labs/lab04/numbers_summary.pynotes/lab04-notes.md- PowerShell 或 VS Code 终端输出截图
- 一份
git diff检查记录 - 一个完成 Lab 4 的 Git 检查点
笔记要求
在 notes/lab04-notes.md 中包括:
- 运行过的命令;
- 四个概念检查问题的回答;
- OpenCode Go、DeepSeek V4 Pro 和完整模型标识;
- 只读检查、实现和解释三个 OpenCode 提示词;
git diff中最重要的一处改动;- 预期值;
- 输出是否符合预期;
- 一个你手动检查的内容。