- 示例工程
【免费下载链接】modern-software-dev-assignments
Assignments for CS146S: The Modern Software Dev (Stanford University Fall 2026/2025)
CS146S(Stanford《The Modern Software Developer》)第一周作业要求通过本地 Ollama 运行的开源 LLM,亲手实践 K-shot、Chain-of-Thought、Tool Calling、Self-Consistency、RAG 与 Reflexion 六种提示技术。本文以 week1/assignment.md 为骨架,结合仓库中六个可直接运行的 Python 测试脚本,完整讲解环境搭建、每种技术的任务设定、源码测试逻辑与提示词撰写要点,帮助你迭代出能通过脚本校验的最终提示词。
课程背景与本周目标
这是 CS146S 系列作业的第一周:LLM Prompting Playground。仓库根目录的 README.md 说明项目依赖 Python 3.12,而 week1/README.md 明确指出本练习的核心是 "Practice core LLM prompting techniques essential to using and understanding coding LLMs"——即通过设计提示词来理解和使用编码类 LLM。
完整的任务说明位于 week1/assignment.md,其核心要求只有三条:
- 阅读每个源文件顶部的任务描述;
- 只修改代码中标有
TODO的位置(即编写你的提示词),不要改动模型本身; - 反复迭代直到测试脚本通过,并保存最终的提示词与输出。
这种"脚手架式"设计意味着:框架、评测逻辑、模型参数全部由仓库提供,你要挑战的只有提示词工程本身。
环境搭建:Conda + Poetry + Ollama
1. 创建 Python 3.12 环境并安装依赖
按照顶层 README.md 的 Repo Setup 部分操作:
conda create -n cs146s python=3.12 -y conda activate cs146s curl -sSL https://install.python-poetry.org | python - poetry install --no-interactionPoetry 会在激活的 Conda 环境内按 pyproject.toml 安装项目依赖(包括ollamaPython 客户端与python-dotenv,这两个库在六个练习文件中被直接 import)。
2. 安装并启动 Ollama
Ollama 用于在本地运行不同规格的 SOTA 开源 LLM。按 week1/assignment.md 的 Installation 一节,不同平台安装方式如下:
- macOS(Homebrew):
brew install --cask ollama ollama serve - Linux(推荐):
curl -fsSL https://ollama.com/install.sh | sh - Windows:从 ollama.com/download 下载并运行安装程序。
安装后用ollama -v验证版本。
3. 拉取所需模型(只需一次)
运行测试脚本前,必须预先拉取两个模型:
ollama run mistral-nemo:12b ollama run llama3.1:8b两个模型在六个练习中分工明确:mistral-nemo:12b用于 K-shot 练习,llama3.1:8b用于其余五种技术。如果本地机器性能有限,这决定了单次推理的耗时,也提醒我们测试脚本都会执行多轮(NUM_RUNS_TIMES次)以保证结果统计意义。
六种提示技术的源码级拆解
下面按 week1/assignment.md 的 Techniques and source files 列表逐一展开,每小节先交代任务,再结合源码说明测试逻辑与提示词设计要点。
K-shot Prompting ——week1/k_shot_prompting.py
任务:让模型只输出反转字母顺序后的单词,输入词是httpstatus,期望输出sutatsptth。
测试逻辑(week1/k_shot_prompting.py):
- 使用
mistral-nemo:12b,temperature=0.5,共运行NUM_RUNS_TIMES = 5次; - 只要任意一次输出与
EXPECTED_OUTPUT完全一致即判定SUCCESS; - 每次运行都打印实际输出与期望输出,便于你观察模型失误模式。
提示词要点:你的YOUR_SYSTEM_PROMPT(第 10 行的 TODO)应当包含若干"输入→输出"示例对(few-shot 示例),让模型从示例中习得"仅输出反转结果、不加任何解释"的格式约束。示例应覆盖大小写处理与"只输出单词本身"的规则;由于有 5 次机会且温度 0.5,格式约束越严格,命中率越高。注意用户提示词固定为 week1/k_shot_prompting.py 中内容,不能修改。
Chain-of-Thought(思维链)——week1/chain_of_thought.py
任务:求解模幂问题3^{12345} (mod 100),要求最后一行输出Answer: 43。
测试逻辑(week1/chain_of_thought.py):
- 使用
llama3.1:8b,temperature=0.3,运行 5 次; - 关键在
extract_final_answer()(第 25-40 行):用正则(?mi)^\s*answer\s*:\s*(.+)\s*$找出最后一行Answer:开头的文本,并把其中的数字规整为Answer: <number>形式后再与期望值比对。
提示词要点:由于用户提示词已要求"先解题、最后一行输出 Answer",你的 system prompt 应鼓励模型逐步推理("think step by step"),同时明确约束最后一行必须是Answer: <数字>。注意正则取的是最后一条匹配,任何推理过程中出现的Answer:前缀行都会被忽略——这是设计的容错点,你的提示词不必担心推理过程中的中间标注。模运算类题目对纯数值模型容易出错,CoT 提示正是为了让模型先展开运算再收敛答案。
Tool Calling(工具调用)——week1/tool_calling.py
任务:让模型以结构化 JSON 的形式调用工具output_every_func_return_type,该工具会扫描本文件内所有顶层函数并返回"函数名: 返回类型"列表,期望输出与实际扫描结果完全一致。
测试逻辑(week1/tool_calling.py):
- 使用
llama3.1:8b,temperature=0.3,运行 3 次; extract_tool_call()(第 87-100 行)从模型输出中解析 JSON 对象(兼容 ```json 代码块包裹);execute_tool_call()(第 115-133 行)按tool名查TOOL_REGISTRY并传入args执行;- 期望值由
compute_expected_output()直接调用工具本体生成,是"真值"——不是字符串比对,而是工具执行结果的逐字比较。
提示词要点:你的YOUR_SYSTEM_PROMPT必须让模型学会输出形如{"tool": "output_every_func_return_type", "args": {"file_path": "..."}}的 JSON 调用。重点是教会模型:
- 工具的名称与参数签名(
file_path可省略,缺省时指向本文件); - 输出必须是单个合法 JSON 对象,且
args必须是对象类型(execute_tool_call第 122-124 行对此做了强校验); - 不要在 JSON 外夹杂解释文本,否则会触发
extract_tool_call的解析失败分支。
同时可阅读 week1/tool_calling.py 中add、greet两个示例函数——它们是本文件内被扫描的对象,提示词中也可以提到"列出文件中所有函数返回类型"这类任务语义。
Self-Consistency Prompting(自一致性)——week1/self_consistency_prompting.py
任务:解一道行程文字题(60 英里骑行、两次停靠,求两次停靠间距离),期望Answer: 25。
测试逻辑(week1/self_consistency_prompting.py):
- 使用
llama3.1:8b,temperature=1(故意调高以产生多样化的推理路径),运行 5 次; - 每次用
extract_final_answer()提取Answer: <数字>,收集 5 个答案后用collections.Counter做多数投票(counts.most_common(1)[0]); - 只有当多数答案等于期望输出才算
SUCCESS,并打印完整答案分布供调试。
提示词要点:你的 system prompt 应(a)要求模型先逐步推理、最后一行给出Answer: <数字>;(b)明确"多次独立求解、选择最一致的结果"的自一致性语义。高温度 + 多次采样 + 多数投票正是 Self-Consistency 的核心思想:单次可能出错,但多数一致答案更可信。注意:若 5 次全部失败,脚本会打印每个答案的票数,你可以据此判断模型是系统性误解(多数票相同但错误)还是随机失误。
RAG(检索增强生成)——week1/rag.py
任务:给定一份 API 文档语料,让模型基于文档编写fetch_user_name(user_id: str, api_key: str) -> str函数,代码中必须包含def fetch_user_name(、requests.get、/users/、X-API-Key、return五个关键片段。
测试逻辑(week1/rag.py):
- 语料从 week1/data/api_docs.txt 加载(Base URL、
X-API-Key鉴权头、GET /users/{id}端点、返回 JSON 结构均在此文档中); - 使用
llama3.1:8b,temperature=0.0,运行 5 次;extract_code_block()提取最后一个 Python 代码块后,逐条检查五个REQUIRED_SNIPPETS是否出现,缺一即失败; - 关键钩子在
YOUR_CONTEXT_PROVIDER(第 54-59 行,TODO):你的检索策略决定了上下文质量——返回[]模拟"无上下文",返回[corpus[0]]则注入完整 API 文档; make_user_prompt()(第 62-76 行)会把上下文拼进用户消息,并注明 "Context (use ONLY this information)",即约束模型只能依据给定文档作答。
提示词要点:这是"检索"与"生成"双环节任务。你需要在YOUR_CONTEXT_PROVIDER中实现简单选择(如按关键词user命中相关文档),并在YOUR_SYSTEM_PROMPT中强调:严格使用上下文中给出的 Base URL、鉴权头与端点格式;非 200 响应要raise;函数只返回name字符串;输出为单个 Python 代码块。由于校验是片段级而非精确匹配,提示词的核心目标是保证五个必需片段全部出现在最终代码里。
Reflexion(反思强化)——week1/reflexion.py
任务:首先生成is_valid_password(password: str) -> bool函数,再用"反思"环节基于失败用例改进代码,直到通过 4 条密码校验用例(如Password1!合法、缺大写/缺数字/缺特殊字符均不合法)。
测试逻辑(week1/reflexion.py):
- 使用
llama3.1:8b,temperature=0.2,NUM_RUNS_TIMES = 1(本脚本只做一轮生成 + 一轮反思); evaluate_function()(第 50-79 行)用TEST_CASES逐一执行生成代码,失败时自动生成诊断(缺大写/缺数字/缺特殊字符等),这构成了反思的"反馈信号";your_build_reflexion_context()(第 94-99 行,TODO)需要把上一版代码 + 失败诊断拼成反思阶段的用户消息;SYSTEM_PROMPT已内置(第 11-15 行)无需改动;你的 TODO 是YOUR_REFLEXION_PROMPT与your_build_reflexion_context。
提示词要点:Reflexion 的核心是"利用失败信息自我修正"。你的YOUR_REFLEXION_PROMPT应指示模型:阅读上一版实现与具体失败用例,分析漏掉了哪条校验规则(如未检查特殊字符!@#$%^&*()-_集合),重写一个完整覆盖所有规则的最小实现;your_build_reflexion_context则应把失败诊断逐条格式化后交给模型。注意load_function_from_code用exec动态加载生成代码,因此提示词要约束模型"只输出一个可独立运行的 Python 代码块,定义is_valid_password函数"。
交付物与评分规则
按 week1/assignment.md 的 Deliverables 与 Evaluation rubric:
- 交付物:每个技术文件中的
TODO全部解决;保存每个技术的最终提示词与运行输出;提交包含六个文件的完整代码,并逐项核对所有TODO均已填充。 - 评分:总分 60 分,六个技术各 10 分,对应 week1/README.md 中 "LLM Prompting Playground" 的六个练习文件。也就是说,每个文件脚本打印
SUCCESS即获得该技术的满分。
迭代方法论与常见坑
从六个脚本的源码可以总结出一套通用迭代流程:
- 先跑基线:TODO 留空(如
YOUR_SYSTEM_PROMPT = "")直接运行脚本,观察模型"零提示"下的行为与失败输出格式; - 定位评测规则:先读懂测试函数——是精确字符串比对(K-shot、Tool Calling)、正则抽取后比对(CoT、Self-Consistency)、片段包含校验(RAG)还是执行用例校验(Reflexion),据此设计提示词的输出格式约束;
- 单变量迭代:一次只改一个约束(如先加格式约束、再加示例、再调温度无关的措辞),因为模型与
NUM_RUNS_TIMES、温度等参数均不可改; - 利用失败打印:各脚本都会打印期望输出与实际输出(或缺失片段、答案分布、失败诊断),这是最直接的调试信号;
- 区分"格式失败"与"能力失败":RAG 缺
X-API-Key多半是上下文没注入或提示词没强调鉴权头;CoT 答案不对则是推理质量问题,应强化"逐步运算"的引导。
需要特别提醒的是,所有提示词都必须放入**系统消息(system prompt)**位置——六个脚本调用chat()时都将system_prompt作为messages[0],用户消息由脚本固定拼接。若你把提示词写进 TODO 之外的任何代码位置,都会破坏评测口径。
小结
CS146S 第一周通过一个"只改提示词"的受控环境,把六种最重要的 LLM 应用技术浓缩为六个可重复、可评分、可调试的练习:K-shot 教你用示例约束输出格式,CoT 教你引导推理过程,Tool Calling 教你让模型产出可执行的工具调用 JSON,Self-Consistency 教你用多次采样 + 多数投票提升可靠性,RAG 教你检索与生成的协同,Reflexion 教你用失败反馈自我修正。从 week1/assignment.md 出发、配合六个源文件与 week1/data/api_docs.txt,你可以在完全离线、免费的本地环境中,系统掌握理解与使用编码 LLM 的核心提示工程能力。
- 示例工程
【免费下载链接】modern-software-dev-assignments
Assignments for CS146S: The Modern Software Dev (Stanford University Fall 2026/2025)
相关推荐
Latitude-LLM项目中的Step-Back Prompting技术详解
Latitude LLM项目中的Step Back Prompting技术详解 引言:重新思考AI提示工程 在人工智能领域,如何让大语言模型 LLM 产生更优质
Phoenix项目中的Few-Shot Prompting技术详解
Phoenix项目中的Few Shot Prompting技术详解 引言:为什么Few Shot Prompting如此重要? 在AI应用开发中,你是否遇到过这
可观测性AI 评测LLMOpsAI 应用人工智能K-shot prompting实战:在modern-software-dev-assignments中教会LLM反转单词
K shot prompting实战:在modern software dev assignments中教会LLM反转单词 K shot prompting 是
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考