返回课程总览

实验 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

一次完整调用包含以下步骤:

  1. 外部程序向 LLM 提供工具说明。
  2. LLM 根据任务和上下文生成工具名称与输入参数。
  3. 外部程序解析请求并执行对应工具。
  4. 工具返回文件内容、命令输出或错误信息。
  5. 外部程序把返回结果加入上下文,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 中用自己的话回答:

  1. LLM 如何通过预测下一个 token 生成完整回答?
  2. 为什么 LLM 生成一条 PowerShell 命令并不等于已经运行了它?
  3. 一次工具调用中,LLM 和外部程序分别负责什么?
  4. 为什么 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 的说明解压。

准备与运行

  1. starters/lab04/ 中的 starter 文件复制到 labs/lab04/
  2. notes/lab04-notes.md 中记录实验过程。
  3. 运行 starter 文件:
python labs\lab04\hello.py
python labs\lab04\average.py
  1. 在 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.pyaverage.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 statusgit 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.py
  • notes/lab04-notes.md
  • PowerShell 或 VS Code 终端输出截图
  • 一份 git diff 检查记录
  • 一个完成 Lab 4 的 Git 检查点

笔记要求

notes/lab04-notes.md 中包括:

  • 运行过的命令;
  • 四个概念检查问题的回答;
  • OpenCode Go、DeepSeek V4 Pro 和完整模型标识;
  • 只读检查、实现和解释三个 OpenCode 提示词;
  • git diff 中最重要的一处改动;
  • 预期值;
  • 输出是否符合预期;
  • 一个你手动检查的内容。