- 示例工程
【免费下载链接】modern-software-dev-assignments
Assignments for CS146S: The Modern Software Dev (Stanford University Fall 2026/2025)
本文以 Stanford 课程 CS146S《现代软件开发》第一周作业(week1/assignment.md)为核心,系统讲解 K-shot Prompting、Chain-of-Thought、Tool Calling、Self-Consistency、RAG 与 Reflexion 六种提示词技术的原理、源码实现与工程验证方式。读者完成本文后,将能基于 Ollama 在本地运行开源大模型,为每种技术设计可复现的提示词并通过自动化测试。
作业概览:为什么用"提示词工程"作为第一课
该作业的目标很明确:通过为 6 个具体任务手工构造提示词,实践多种提示词技术。每个任务的指令位于对应源文件顶部,学生需要找出代码中所有标记为TODO的位置——这是唯一需要改动的地方,作业明确要求"不要动模型本身"(即不改动模型选择、采样参数等)。换句话说,作业考查的是用提示词语言驱动模型行为的能力,而非调参或微调能力。
作业仓库位于项目根目录,安装步骤见顶层 README.md,完整作业描述见 week1/assignment.md。6 个技术文件全部位于 week1/ 目录下:
| 技术 | 源文件 |
|---|---|
| K-shot prompting(少样本提示) | week1/k_shot_prompting.py |
| Chain-of-thought(思维链) | week1/chain_of_thought.py |
| Tool calling(工具调用) | week1/tool_calling.py |
| Self-consistency prompting(自洽性提示) | week1/self_consistency_prompting.py |
| RAG(检索增强生成) | week1/rag.py |
| Reflexion(反思式自我改进) | week1/reflexion.py |
评分总计 60 分:每种技术完成一个可用的 prompt 得 10 分,6 种技术共 60 分。这意味着文章接下来分析的每个文件都直接对应 10 分。
环境搭建:从 Python 环境到本地大模型
1. 仓库依赖安装(Python 3.12 + Poetry)
作业要求先完成顶层 README.md 中描述的安装。该步骤以 Python 3.12 为目标版本,采用 Anaconda + Poetry 的组合:
conda create -n cs146s python=3.12 -y conda activate cs146s curl -sSL https://install.python-poetry.org | python - poetry install --no-interaction从 pyproject.toml 可以看到,作业运行所需的 Python 依赖包括ollama ^0.5.3(Ollama 官方 Python 客户端)、python-dotenv(加载环境变量)、openai等;开发依赖包括pytest、httpx、black、ruff与pre-commit。所有 6 个提示词脚本都通过from ollama import chat与本地模型对话。
2. Ollama 安装与验证
作业使用Ollama在本地运行多种当前主流开源 LLM,按操作系统提供三种安装方式:
- macOS(Homebrew):
brew install --cask ollama ollama serve - Linux(推荐):
curl -fsSL https://ollama.com/install.sh | sh - Windows:从 ollama.com/download 下载并运行官方安装器。
安装完成后验证版本:
ollama -v3. 拉取作业所需模型(只需一次)
运行测试脚本前,必须预先拉取两个模型(除非日后手动删除,否则只需拉取一次):
ollama run mistral-nemo:12b ollama run llama3.1:8b两个模型在 6 个任务中的分工是固定的:只有 K-shot 任务使用mistral-nemo:12b,其余 5 个任务全部使用llama3.1:8b。这一点可以直接从各源文件的chat(model=...)调用中确认(如 k_shot_prompting.py 与 chain_of_thought.py)。
六种提示词技术的源码级解读
一、K-shot Prompting:少样本示范引导输出格式
K-shot(少样本)提示的核心思想是:在提示中给出若干输入-输出示例,让模型"模仿"示例的格式与推理方式。本任务的 k_shot_prompting.py 只要求反转单词httpstatus的字母顺序,期望输出为sutatsptth。
源码中的关键工程细节:
NUM_RUNS_TIMES = 5 # 最多尝试 5 次,任一成功即通过 YOUR_SYSTEM_PROMPT = "" # TODO:唯一需要填写的变量 USER_PROMPT = """ Reverse the order of letters in the following word. Only output the reversed word, no other text: httpstatus """ EXPECTED_OUTPUT = "sutatsptth"测试函数 test_your_prompt 以temperature=0.5(options={"temperature": 0.5})对mistral-nemo:12b连续调用 5 次,只要有一次输出与期望完全一致即打印SUCCESS并通过。由于模型具有随机性,系统提示词必须做到两点:给出正确的反转示范(K-shot 的 "K" 就体现在这里),并严格约束输出只包含反转结果,避免模型附带解释或格式杂质。
二、Chain-of-Thought:让模型分步推理后再给答案
思维链(CoT)通过要求模型"先逐步推理,再给出结论",显著提升复杂数学与逻辑问题的成功率。chain_of_thought.py 的任务是计算3^{12345} (mod 100),期望输出为Answer: 43。
该任务在工程实现上有两个值得注意的设计:
- 输出格式协议:用户提示明确要求
give the final answer on the last line as "Answer: <number>",这是为了配合后端的解析逻辑。 - 正则解析器:extract_final_answer 用
re.findall(r"(?mi)^\s*answer\s*:\s*(.+)\s*$", text)找出最后一条以Answer:开头的行,再从中提取数字并规范化为Answer: <number>。这意味着即使模型输出冗长的推理过程,测试也只关心最后一行答案——这正是 CoT 提示"推理过程随意、结论必须规范"的典型工程形态。
测试以temperature=0.3调用llama3.1:8b最多 5 次,只要解析后的最终答案等于Answer: 43即通过。实践要点:系统提示词应引导模型先展示指数模运算的逐步化简(如利用欧拉定理 φ(100)=40 简化指数),再用固定格式收尾。
三、Tool Calling:让模型学会"调用工具"而非直接作答
工具调用(函数调用)是 Agent 能力的基石:模型不直接给出答案,而是输出一次对注册工具的调用请求,由执行器解析并运行。tool_calling.py 构建了一个最小但完整的工具调用闭环:
工具注册表(即"执行器"侧):
TOOL_REGISTRY: Dict[str, Callable[..., str]] = { "output_every_func_return_type": output_every_func_return_type, }output_every_func_return_type通过 Python 的ast模块静态解析目标文件,返回每个顶层函数形如name: return_type的清单(tool_calling.py);脚本内还预置了add(a: int, b: int) -> int与greet(name: str) -> str两个样例函数供解析。
模型侧协议:模型必须输出一个 JSON 对象,包含工具名与参数,例如:
{"tool": "output_every_func_return_type", "args": {"file_path": "tool_calling.py"}}extract_tool_call 负责解析这段 JSON(兼容被 ``` 代码围栏包裹的情况),execute_tool_call 则查表调用对应函数,并在参数中智能补全file_path默认值。测试流程(test_your_prompt)先计算"真实结果"作为基准,再要求模型输出工具调用、执行之,最后比对两者是否一致。注意此处NUM_RUNS_TIMES = 3,且temperature=0.3。
实践要点:YOUR_SYSTEM_PROMPT必须向模型描述可用的工具名称、参数结构、JSON 输出格式以及"每次只调用工具、不直接回答"的行为约束——模型只有在系统提示词中看到工具说明时才会生成合法的调用 JSON。
四、Self-Consistency Prompting:多次采样 + 多数投票
自洽性(Self-Consistency)提示是对 CoT 的强化:用高温度多次独立采样,再对答案做多数投票,从而摊平单次推理的随机错误。self_consistency_prompting.py 的题目是一个简单的行程应用题:
Henry made two stops during his 60-mile bike trip. He first stopped after 20 miles. His second stop was 15 miles before the end of the trip. How many miles did he travel between his first and second stops?
期望输出为Answer: 25(第一次停在 20 英里处,第二次停在 60−15=45 英里处,相距 25 英里)。
其核心投票逻辑在 test_your_prompt 中:
for idx in range(NUM_RUNS_TIMES): # NUM_RUNS_TIMES = 5 response = chat(model="llama3.1:8b", ..., options={"temperature": 1}) final_answer = extract_final_answer(output_text) answers.append(final_answer.strip()) counts = Counter(answers) # 对 5 次采样结果计数 majority_answer, majority_count = counts.most_common(1)[0]与 CoT 任务的关键差异是temperature=1.0:较高的采样温度放大输出的多样性,使得投票才有意义;随后Counter对 5 次Answer:行做多数表决,多数答案命中Answer: 25即判定成功。调试时脚本还会打印答案分布,便于观察模型是否在某类错误上系统性跑偏。
五、RAG:检索增强生成,让模型"只看该看的资料"
RAG 解决的是"模型知识不足或过时"的问题:先检索出与问题相关的文档片段,再拼接进提示词,让模型只基于给定上下文作答。本任务(rag.py)让模型根据 API 文档编写一个调用GET /users/{id}接口的 Python 函数fetch_user_name(user_id, api_key) -> str。
知识库来源:DATA_FILES指向 week1/data/api_docs.txt,该文件以极简格式描述 API:
Base URL: https://api.example.com/v1 Authentication: Provide header X-API-Key: <your key> Endpoints: GET /users/{id} - Returns 200 with JSON: {"id": <string>, "name": <string>}检索环节的 TODO:YOUR_CONTEXT_PROVIDER(corpus)(rag.py)负责从语料库中挑选相关文档——默认返回[]模拟"无上下文"情形,作业要求你改成把 API 文档注入上下文,从而体会"有检索 vs 无检索"的显著差异。
提示词拼接:make_user_prompt 把检索结果包装成Context (use ONLY this information):块,并硬性规定四项要求:使用文档中的 Base URL 与端点、发送文档规定的认证头、对非 200 响应 raise、只返回用户名字符串。
验证方式:测试以temperature=0.0(完全确定性)调用llama3.1:8b最多 5 次,用必需片段匹配而非整串比对来评判代码正确性,REQUIRED_SNIPPETS检查生成的代码是否包含:
REQUIRED_SNIPPETS = [ "def fetch_user_name(", "requests.get", "/users/", "X-API-Key", "return", ]这 5 个片段从函数签名、HTTP 调用、端点路径、认证头到返回值,覆盖了 RAG 任务的核心验收点;缺任一片段都会打印Missing required snippets并进入下一轮。
六、Reflexion:失败 → 反思 → 重写 的自我改进循环
Reflexion 是"具身智能体"风格的自我改进范式:模型先写代码,用测试套件求值,拿到失败诊断后再反思并重写。reflexion.py 的任务是生成一个is_valid_password(password: str) -> bool函数,密码需同时包含大写、小写、数字与特殊字符。
真实测试套件(作为求值基准,reflexion.py):
SPECIALS = set("!@#$%^&*()-_") TEST_CASES: List[Tuple[str, bool]] = [ ("Password1!", True), # valid ("password1!", False), # missing uppercase ("Password!", False), # missing digit ("Password1", False), # missing special ]求值诊断器:evaluate_function 对每个测试用例实际调用生成的函数,若结果不符,会基于真值规则生成可读诊断,例如Failing checks: missing uppercase, missing digit——这些诊断字符串正是喂给反思环节的"反思素材"。
反思环节的 TODO:YOUR_REFLEXION_PROMPT与your_build_reflexion_context(prev_code, failures)(reflexion.py)是两个需要填写的关键点:前者是反思系统提示词,后者把上一版代码和失败诊断组装成用户消息。整个流程由 run_reflexion_flow 编排:先用SYSTEM_PROMPT生成初始实现(temperature=0.2,NUM_RUNS_TIMES=1),若测试全过直接成功;否则执行单轮反思——把失败信息回传给模型,要求其输出改进版代码,再重新求值。由此可以直观看到"带诊断的反思"相比"盲目重试"的提升。
交付物与评分标准
作业对最终提交有明确要求(week1/assignment.md):
- 阅读每个文件顶部的任务描述;
- 设计并运行提示词(找出代码中所有
TODO,这是唯一允许改动的位置,不要改动模型相关配置); - 迭代改进提示词直至测试脚本通过(脚本打印
SUCCESS即通过); - 为每种技术保存最终提示词与对应输出;
- 提交包含 6 个提示词技术文件完整代码的版本,逐一确认所有
TODO均已解决。
评分规则(共 60 分):6 种提示词技术各 10 分,每种技术只要提交了可用的 prompt 即可得分。
小结:一条完整的"提示词工程"方法论
纵向看这 6 个任务,其实勾勒出一条从"单次提示"到"多轮自我改进"的能力阶梯:
- K-shot解决"输出格式与风格模仿";
- CoT解决"复杂推理";
- Tool Calling解决"模型与外部工具/代码的对接";
- Self-Consistency用采样+投票解决"单次推理的随机性";
- RAG用检索注入解决"知识时效与范围";
- Reflexion用失败诊断驱动"自我迭代"。
在每个任务中,测试脚本都扮演了"客观裁判"的角色——它们要么比对精确字符串(K-shot、CoT、Self-Consistency)、要么校验 JSON 工具调用并比对真实结果(Tool Calling)、要么检查必需代码片段(RAG)、要么运行真实测试用例(Reflexion)。这种"提示词设计 + 自动化验证"的组合,正是现代软件工程中评估与迭代 LLM 应用的标准姿势,也是后续周次作业(FastAPI 后端、测试与 CI 等)的知识铺垫。
- 示例工程
【免费下载链接】modern-software-dev-assignments
Assignments for CS146S: The Modern Software Dev (Stanford University Fall 2026/2025)
相关推荐
LLM Prompting Playground:在 CS146S 项目中用 Ollama 实战六种核心 Prompting 技术
LLM Prompting Playground:在 CS146S 项目中用 Ollama 实战六种核心 Prompting 技术 CS146S(Stanfor
示例工程提示工程基础实战指南:基于 generative-ai-for-beginners 掌握 LLM 提示词的设计与优化
提示工程基础实战指南:基于 generative ai for beginners 掌握 LLM 提示词的设计与优化 本文是生成式 AI 入门课程(genera
教程人工智能大模型终极Prompt Engineering指南:掌握AI提示词工程的核心策略与实战技巧
终极Prompt Engineering指南:掌握AI提示词工程的核心策略与实战技巧 Prompt Engineering是一种通过精心设计输入提示来引导AI模
文档教程提示工程大模型人工智能RAGAI Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考