skill 到底是什么传统的AI的知识锁在模型的参数里，想让模型学习新技能？参数传统方式skill处理过程收集数据 → 处理数据 → 参数训练 → 部署编辑SKILL.md 文件 → 下次执行时触发成本¥10000 - ¥1000000+¥0周期数周 - 数月即时Skill就像是给base model 外挂一个可热插拔的LoRA适配器，但完全不需要训练。编辑Markdown文件，模型的行为就改变了。技能是一个目录，其中包含一个SKILL.md 文件，该文件包含组织有序的文件夹，其中包含指令、脚本和资源，这些指令、脚本和资源为 Agent 提供额外的功能。Tool vs Skill 的一个关键区分概念本质作用例子Tool模型能做什么执行动作bash、read_file、write_file、WebSearchSkill模型知道怎么做指导决策PDF处理、MCP构建、前端设计、代码审查工具是能力的边界：没有bash工具，模型无法执行命令技能是知识的注入：没有前端设计Skill，模型写出的UI前篇一律[scode type="lblue"]通用Agent + 优秀的Skill = 特定领域的专家 Agent[/scode]Skill价值：同一个模型，加载不同的Skill，就变成不同的专家[scode type="lblue"]Agent能力上限 = 模型能力 + Skill 质量[/scode]模型能力是基座，Skill质量决定这个基座能发挥到什么程度。一个优秀的Skill，能让通用Agent在特定领域的变现超过没有Skill加持的更强大模型。判断标准Token效率🫏：段落是否值得它的开销[collapse status="false" title="Anthropic 官方 skill-creator 规范"]Concise is Key.The context window is a public good. Skills share the context window with everything else Claude needs: system prompt, conversation history, other Skills' metadata, and the actual user request.(Context window 是公共资源。一个 Skill 占用的 token，会挤压其他内容的空间——系统提示、对话历史、其他 Skill 的元数据、用户的实际请求。)Default assumption: Claude is already very smart.Only add context Claude doesn't already have. Challenge each piece of information: "Does Claude really need this explanation?" and "Does this paragraph justify its token cost?"(当你写一段"什么是 PDF"的解释时，你在浪费这个公共资源。Claude 已经知道什么是 PDF。这 100 个 token 本可以用来存放更有价值的信息。)[/collapse]通过三个问题，判断每段话的价值模型真的不知道这个吗？删掉它会影响任务完成吗？这100个 token 能换来什么价值？[scode type="lblue"]好 Skill = 专家独有的知识 - 模型已知[/scode]这个公式是判断Skill价值的根本标准，可以将 Skill 理解为 专家大脑的压缩文件：把一个设计师 10 年的审美积累缩成 43 行，把一个文档专家的操作经验压缩成 200 行决策树。压缩的必须是模型没有的东西，否则就是垃圾压缩❤️心智模型 vs ⚙️机械步骤：传递的是什么[collapse status="false" title="Anthropic 官方 Skill 示例，特别是 frontend-design、canvas-design"]Before coding, understand the context and commit to a BOLD aesthetic direction: - **Purpose**: What problem does this interface solve? Who uses it? - **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic... - **Differentiation**: What makes this UNFORGETTABLE? NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto), cliched color schemes (purple gradients on white backgrounds)...官方最精简的 Skill——frontend-design，只有 43 行。它没有教 Claude 如何写 CSS。它没有解释什么是 flexbox。它没有列出 Step 1、Step 2、Step 3。它激活的是 设计师的思维方式：在动手写代码之前，先想清楚几个关键问题---这是专家和新手的本质区别。[/collapse]专家和新手的差异不在于 会不会操作，而在于 如何思考问题。资深的设计师和初学者都会写CSS，但是设计师在写第一行代码之前，脑子里已经有了清晰的审美方案、用户场景、差异化定位。[scode type="lblue"]好的 Skill 传递的是思维方式，而不是机械的操作步骤。[/scode]维度平庸 Skill优秀 Skill内容Step 1、Step 2、Step 3思考框架、决策原则假设Agent 不会做Agent 会做，但不知道怎么想效果Agent 照本宣科Agent 像专家一样思考🧾反模式清单：明确什么不能做[collapse status="false" title="官方 Skill 都包含明确的"NEVER"清单"]frontend-design：NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns...canvas-design：NEVER lose sight of the idea that this should be art, not something that's cartoony or amateur.[/collapse]专家知识的一般是 知道什么能做，另一半是 知道什么绝对不能做[scode type="lblue"]明确的 NENVER清单，告诉 Agent 什么是 垃圾做法[/scode]Description 出发机制：何时被激活[collapse status="false" title="Anthropic 官方 skill-creator 规范"]This is the primary triggering mechanism for your skill, and helps Claude understand when to use the skill. Include both what the Skill does and specific triggers/contexts for when to use it. Include all "when to use" information here - Not in the body. The body is only loaded after triggering.[/collapse]Skill 分三层加载：Layer 1: Metadata（始终在内存中） 只有 name + description ~100 tokens / skill Layer 2: SKILL.md Body（触发后才加载） 详细指南、代码示例、决策树 < 5000 tokens Layer 3: Resources（按需加载） scripts/, references/, assets/ 无限制关键点：description 是唯一始终可见的部分，Agent 根据 description 决定是否激活这个 Skill。如果 description 太模糊，Skill 将无法正确的被触发。好的 description：description: "Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks"[scode type="lblue"]描述功能（what it does）列出出发场景 （when to use）包含关键词（.docx files, tracked changes）[/scode]自由度校验：与任务错弱度匹配官方 skill-creator 规范:Match the level of specificity to the task's fragility and variability: High freedom (text-based instructions): Use when multiple approaches are valid, decisions depend on context. Medium freedom (pseudocode or scripts with parameters): Use when a preferred pattern exists, some variation is acceptable. Low freedom (specific scripts, few parameters): Use when operations are fragile and error-prone, consistency is critical.[scode type="lblue"]不同类型的任务需要不同程度的约束[/scode]任务类型自由度原因示例 Skill创意设计高多种方法有效，差异化是价值frontend-design代码审查中有原则但需要判断代码审查 Skill文件格式操作低操作脆弱，一致性关键docx、xlsx如何判断：问自己：这个任务容错率高还是低？如果 Agent 做错一步，后果是什么？容错率高 ：给原则，不给步骤容错率低 ：给脚本，少参数加载出发设计：Reference 能否被正确使用很多 Skill 有详细的 reference 文档，但 Agent 不读或读太多。假设 Agent 会“聪明的”按需加载是一个错误的认知，必须显示设计加载触发机制。加载率太低 ◄─────────────────────────────────────────────► 过度加载 问题： 问题： - Reference 形同虚设 - 浪费上下文空间 - 知识放了跟没放一样 - 无关信息稀释关键内容 - Agent 不知道何时该加载 - Token 开销不必要增加不同的 Agent 对 Skill 机制的训练程度不同Claude 对Skill 机制有专门的训练，会适时主动加载大多数 Agent 没有专门训练，不会主动加载有些 Agent 过于积极，一次性加载太多在工作流的关键节点嵌入强制加载指令。官方 docx Skill 的做法：### Creating New Document **MANDATORY - READ ENTIRE FILE**: Before proceeding, you MUST read [`docx-js.md`](docx-js.md) (~500 lines) completely from start to finish. **NEVER set any range limits when reading this file.**"MANDATORY"、"MUST"、"NEVER" 不是装饰词，是确保 Agent 执行的关键信号。注意：这条标准只对有 reference 目录的中等/复杂 Skill 重要。简单型 Skill（如 frontend-design，43 行，无 reference）不需要考虑这个问题。Skill的好坏skill 返例# PDF 处理技能 ## 什么是 PDF PDF（Portable Document Format，便携式文档格式）是由 Adobe 公司在 1993 年开发的一种文件格式。它可以在不同的操作系统和设备上保持文档的格式不变，包括字体、图像、排版等元素。PDF 文件可以包含文本、图像、超链接、表单字段、视频等多种元素。 ## PDF 的特点 1. 跨平台兼容性 2. 格式保持一致 3. 支持加密和权限控制 4. 文件大小相对较小 ## 如何读取 PDF 要读取 PDF 文件，你可以使用多种方法： ### 方法一：使用 PyPDF2 Step 1: 首先安装 PyPDF2 库 pip install PyPDF2 Step 2: 导入库 from PyPDF2 import PdfReader Step 3: 打开 PDF 文件 reader = PdfReader("document.pdf") Step 4: 读取页面内容 page = reader.pages[0] text = page.extract_text() ### 方法二：使用 pdfplumber ...问题具体表现后果解释基础概念"什么是 PDF"、"PDF 的特点"浪费 200+ token，Claude 已经知道机械步骤Step 1, 2, 3, 4Claude 已经会写代码，不需要手把手教没有决策指导列了两种方法但没说什么时候用哪种Agent 不知道如何选择没有反模式没有说什么情况会出错Agent 会踩坑没有边缘情况没有提到扫描件、加密 PDF 等遇到特殊情况会失败Skill正例--- name: pdf-processing description: 处理 PDF 文件。当用户需要读取 PDF 文本、提取表格数据、 填写 PDF 表单、合并或拆分 PDF、将 PDF 转换为图片时使用。 --- **# PDF 处理决策树** 根据任务类型选择工具： | 任务 | 首选工具 | 备选 | 何时用备选 | | ------------ | ------------ | ----------- | -------------------------- | | 读取纯文本 | pdftotext | PyMuPDF | 需要保留布局信息 | | 提取表格 | camelot-py | tabula-py | camelot 失败时 | | 填写表单 | PyMuPDF | pdftk | PyMuPDF 不支持的表单类型 | | 合并/拆分 | PyMuPDF | pdftk | 批量处理大量文件 | | 转换为图片 | pdf2image | PyMuPDF | 需要更高分辨率控制 | **## 常见陷阱** 以下情况需要特殊处理： **扫描件 PDF** • 症状：pdftotext 返回空白或乱码 • 原因：PDF 内容是图片，不是文本 • 解决：先用 OCR（tesseract）处理，再提取文本 **加密 PDF** • 症状：读取时报权限错误 • 解决：PyMuPDF 的 `open(path, password=xxx)` 或先用 qpdf 解密 **复杂嵌套表格** • 症状：camelot 提取结果混乱 • 解决：考虑 LLM 辅助解析，或转成图片后用视觉模型 **大文件性能** • 超过 100 页的 PDF，避免一次性加载全部页面 • 使用分页处理：`for page in reader.pages[start:end]` **## 快速参考** # 命令行快速提取文本 pdftotext input.pdf - # 输出到 stdout # 转换为图片（每页一张） pdftoppm -jpeg -r 150 input.pdf output\_prefix维度表现价值不解释基础没有"什么是 PDF"节省 token决策导向决策树告诉你什么情况用什么Agent 能做正确选择常见陷阱扫描件、加密、复杂表格避免踩坑边缘情况大文件性能问题处理特殊场景可操作直接给命令，不给教程立即可用另一个对比：创意型 Skill坏的创意型 Skill：# 前端设计技能 ## 设计原则 1. 保持一致性 2. 注重用户体验 3. 使用合适的颜色 4. 选择易读的字体 5. 做好响应式设计 ## 设计流程 Step 1: 理解需求 Step 2: 制作线框图 Step 3: 选择配色方案 Step 4: 编写 HTML 结构 Step 5: 添加 CSS 样式 Step 6: 实现响应式 Step 7: 测试和优化 ## 常用工具 - Figma - Sketch - Adobe XD问题：全是废话。"保持一致性"、"注重用户体验"——这些 Claude 早就知道。这个 Skill 没有传递任何 Claude 没有的知识。好的创意型 Skill（官方 frontend-design 风格）：--- name: frontend-design description: 创建独特的、生产级的前端界面。当用户要求构建网页组件、页面、 应用程序、海报、仪表板时使用。生成有创意、有品味的代码和 UI 设计。 --- # 设计思维 在写任何代码之前，先回答这些问题： **Purpose**：这个界面解决什么问题？谁在用它？ **Tone**：选择一个极端方向——极简主义、最大化混乱、复古未来、有机自然、奢华精致、玩具感、杂志感、粗野主义、装饰艺术... **Differentiation**：什么让这个设计令人难忘？用户会记住什么？ **关键**：选择一个清晰的概念方向，然后精确执行。大胆的最大化和精致的极简都可以——关键是意图明确，而不是强度。 ## 绝对不要做的事 以下是典型的"AI 生成感"设计，必须避免： - 滥用 Inter、Roboto、Arial 字体 - 紫色渐变配白色背景 - 所有圆角都是 8px - 千篇一律的卡片布局 - 没有个性的 cookie-cutter 风格 ## 应该追求的 - **字体**：选择有个性的字体。把一个独特的展示字体和精致的正文字体搭配。 - **颜色**：承诺一个连贯的审美。主色调配锐利的强调色，胜过胆怯的平均分配。 - **动效**：聚焦高影响力时刻——一个精心编排的页面加载动画，胜过散落的微交互。 - **空间**：意外的布局。不对称。重叠。对角线流动。打破网格的元素。 - **背景**：创造氛围和深度，而不是默认纯色。渐变网格、噪点纹理、几何图案。 ## 执行原则 **匹配复杂度和愿景**： - 最大化设计 → 需要复杂代码、大量动画和效果 - 极简设计 → 需要克制、精确、细致的间距和字体处理 优雅来自于对愿景的良好执行，而不是堆砌效果。为什么好：维度表现思维框架Purpose/Tone/Differentiation 三个问题明确反模式"绝对不要做的事"清单具体方向字体、颜色、动效、空间、背景各有指导执行原则复杂度匹配愿景不教技术没有解释 CSS，Claude 已经会3.4 第三个对比：代码审查 Skill这个例子展示如何把一个日常任务变成高质量 Skill。坏的代码审查 Skill：# 代码审查技能 ## 什么是代码审查 代码审查是软件开发过程中，由团队成员对代码变更进行检查和评估的活动。 它可以帮助发现 bug、提高代码质量、分享知识... ## 为什么要做代码审查 1. 发现潜在的 bug 2. 提高代码可读性 3. 促进团队知识共享 4. 确保代码符合规范 ## 如何进行代码审查 Step 1: 阅读代码变更 Step 2: 理解代码的目的 Step 3: 检查是否有 bug Step 4: 检查代码风格 Step 5: 写评论反馈 Step 6: 讨论和修改问题：全是废话。Claude 知道什么是代码审查，知道为什么要做。Step 1-6 也是显而易见的流程。这个 Skill 没有传递任何专家独有的知识。好的代码审查 Skill：--- name: code-review description: 审查代码质量和正确性。当用户要求 review PR、检查代码、 找 bug、评估代码质量时使用。 --- # 审查优先级 不是所有问题都同等重要。按以下顺序审查： 1. **安全漏洞**（必须修复） - 注入攻击、权限泄露、敏感数据暴露 2. **逻辑错误**（必须修复） - 边界条件、空值处理、并发问题 3. **性能问题**（建议修复） - N+1 查询、内存泄漏、不必要的重复计算 4. **可维护性**（可选） - 代码风格、命名、注释 # 思维模式 审查每段代码时，问自己： - **理解**：6 个月后的新人能看懂这段代码吗？ - **定位**：如果这里出 bug，能快速定位问题吗？ - **简化**：有没有更简单的写法实现同样功能？ # 绝对不要做 - 一次提 20 个问题（挑最重要的 3-5 个，其他放在"nit"里） - 只说"这里有问题"不说怎么改（要给具体建议或代码示例） - 吹毛求疵（专注真正影响的问题，不要纠结空格和换行） - 用"我觉得"开头（用"建议"或直接说原因） # 评论模板 **必须修复**： > [MUST] 这里存在 SQL 注入风险。用户输入未经转义直接拼接到查询中。 > 建议使用参数化查询：`db.query("SELECT * FROM users WHERE id = ?", [userId])` **建议修复**： > [SUGGEST] 这个循环内有 N+1 查询问题，在数据量大时会很慢。 > 建议改用批量查询：`User.find({ id: { $in: userIds } })` **小问题**： > [NIT] 变量名 `d` 不够清晰，建议改为 `dateCreated`。区别总结：维度坏 Skill好 Skill概念解释解释什么是代码审查直接跳过流程Step 1-6无（Claude 已知）优先级无明确的 4 级优先级思维方式无3 个核心问题反模式无4 条"绝对不要"可操作性空泛建议具体评论模板这就是核心公式的体现：好 Skill = 专家独有的知识 - Claude 已有的知识。好的代码审查 Skill 传递的是资深工程师的审查直觉和经验，不是代码审查的定义和流程。设计检查清单基础规范 [ ] 有 YAML frontmatter，包含 name 和 description [ ] description 包含"做什么"和"什么时候用" [ ] SKILL.md < 500 行 内容质量 [ ] 没有解释 Claude 已知的基础概念 [ ] 没有机械的 Step 1, 2, 3 [ ] 有明确的反模式清单（NEVER list） [ ] 有决策树或选择指导（如果有多种路径） [ ] 有常见陷阱和边缘情况 加载机制（仅有 reference 的 Skill） [ ] 每个 reference 有明确的加载触发条件 [ ] 触发条件嵌入在工作流步骤中 [ ] 有防止过度加载的机制 自由度 [ ] 创意任务 → 高自由度（原则而非步骤） [ ] 脆弱操作 → 低自由度（精确脚本）总结好的 Agent Skill 不是教程，而是 专家知识的外化形式。把一个领域专家的思维方式、决策原则、反模式直觉、边缘情况经验，压缩成一个可加载的 Markdown 文件。当 Agent 加载这个文件时，它不是在"学习操作步骤"，它是在继承一种专家思维。写 Skill 之前，问自己：这个领域的顶级专家是如何思考的？他们做决策的核心原则是什么？他们踩过什么坑？他们绝对不会做什么？什么知识是模型不知道但必须知道的？好 Skill = 专家独有的知识 - Claude 已有的知识好 Skill = 高压缩比 + 高信息密度垃圾 Skill = 压缩了 Claude 已经知道的东西工具让模型能做事，技能让模型知道怎么做相关链接：shareAI-skills 仓库：https://github.com/shareAI-lab/shareAI-skillsskill-judge 评估工具：https://github.com/shareAI-lab/shareAI-skills/tree/main/skills/skill-judgeKode（开源版 Claude Code）：https://github.com/shareAI-lab/Kode
agent skill ： 简化说法：给llm的‘说明文档’- Agent Skill 概念 - 定义：LLM可随时查阅的说明文档 - 功能：简化重复性任务指令，提升任务AI表现 - 应用场景：智能客服、会议总结等 - Agent Skill 基础使用 - 创建步骤 - 指定文件夹创建agent skill - 标记skill.md文件，定义名称、描述、指令 - 使用流程 - 用户请求 - Cloud Code识别并询问使用agent skill - 加载完整skill.md内容 - 模型响应 - 高级功能 - Reference - Script - 渐进式披漏机制 - Agent Skill 与 MCP对比Agent Skill 的核心概念Agent Skill 本质是大模型可随时调用的说明文档，其核心价值在于 “简化重复性任务指令”—— 通过预定义的规则与流程，帮助 AI 更高效地完成标准化工作，典型应用场景包括智能客服（快速匹配应答话术）、会议总结（自动梳理内容框架）等。在Claude中Skill 是一个 markdown 文件，它教 Claude 如何做特定的事情：使用你的团队标准审查 PR、以你喜欢的格式生成提交消息，或查询你公司的数据库架构。当你要求 Claude 做与 Skill 目的相匹配的事情时，Claude 会自动应用它。创建第一个 Skill[tabs][tab name="检查可用的 Skills" active="true"]在创建 Skill 之前，查看 Claude 已经可以访问的 Skills：What Skills are available?Claude 将列出当前加载的任何 Skills。你可能看不到任何，或者你可能看到来自插件或你的组织的 Skills。[/tab][tab name="创建 Skill 目录"]在你的个人 Skills 文件夹中为 Skill 创建一个目录。个人 Skills 在你的所有项目中都可用。（你也可以在 .claude/skills/ 中创建项目 Skills以与团队共享。）bash theme={null} mkdir -p ~/.claude/skills/explaining-code [/tab][tab name="编写 SKILL.md"]每个 Skill 都需要一个 SKILL.md 文件。该文件以 --- 标记之间的 YAML 元数据开始，必须包含 name 和 description，然后是 Claude 在 Skill 活跃时遵循的 Markdown 说明。description 特别重要，因为 Claude 使用它来决定何时应用 Skill。创建 ~/.claude/skills/explaining-code/SKILL.md：--- name: explaining-code description: Explains code with visual diagrams and analogies. Use when explaining how code works, teaching about a codebase, or when the user asks "how does this work?" --- When explaining code, always include: 1. **Start with an analogy**: Compare the code to something from everyday life 2. **Draw a diagram**: Use ASCII art to show the flow, structure, or relationships 3. **Walk through the code**: Explain step-by-step what happens 4. **Highlight a gotcha**: What's a common mistake or misconception? Keep explanations conversational. For complex concepts, use multiple analogies.[/tab][tab name="加载并验证 Skill"]Skills 在创建或修改时会自动加载。验证 Skill 出现在列表中：What Skills are available?[/tab][tab name="测试 Skill"]打开你项目中的任何文件，并向 Claude 提出与 Skill 描述相匹配的问题：How does this code work?Claude 应该要求使用 explaining-code Skill，然后在其解释中包含一个类比和 ASCII 图表。如果 Skill 没有触发，请尝试重新表述以包含描述中的更多关键词，例如”explain how this works”。[/tab][tab name="Skills 存放"]存储 Skill 的位置决定了谁可以使用它：位置路径适用于个人~/.claude/skills/你，跨所有项目项目.claude/skills/在此存储库中工作的任何人插件与[插件]捆绑安装了该插件的任何人如果两个 Skills 有相同的名称，较高的行获胜：个人覆盖项目，项目覆盖插件。[/tab][/tabs]配置 Skills本部分涵盖 Skill 文件结构、支持文件、工具限制和分发选项。编写 SKILL.mdSKILL.md 文件是 Skill 中唯一必需的文件。它有两部分：顶部的 YAML 元数据（--- 标记之间的部分）和告诉 Claude 如何使用 Skill 的 Markdown 说明：--- name: your-skill-name description: Brief description of what this Skill does and when to use it --- # Your Skill Name ## Instructions Provide clear, step-by-step guidance for Claude. ## Examples Show concrete examples of using this Skill.可用的元数据字段你可以在 YAML 前置部分中使用以下字段：字段必需描述name是Skill 名称。必须仅使用小写字母、数字和连字符（最多 64 个字符）。应与目录名称匹配。description是Skill 的功能和何时使用它（最多 1024 个字符）。Claude 使用这个来决定何时应用 Skill。allowed-tools否当此 Skill 活跃时，Claude 可以使用而无需请求权限的工具。支持逗号分隔的值或 YAML 风格的列表。参见限制工具访问。model否当此 Skill 活跃时使用的模型（例如，claude-sonnet-4-20250514）。默认为对话的模型。context否设置为fork 以在具有自己对话历史的分叉子代理上下文中运行 Skill。agent否指定当设置context: fork 时使用哪个代理类型（例如，Explore、Plan、general-purpose 或来自 .claude/agents/ 的自定义代理名称）。如果未指定，默认为 general-purpose。仅在与 context: fork 结合时适用。hooks否定义限定于此 Skill 生命周期的 hooks。支持PreToolUse、PostToolUse 和 Stop 事件。user-invocable否控制 Skill 是否出现在斜杠命令菜单中。不影响Skill 工具或自动发现。默认为 true。参见控制 Skill 可见性。有关完整的编写指导，包括验证规则，请参阅最佳实践指南。更新或删除 Skill要更新 Skill，直接编辑其 SKILL.md 文件。要删除 Skill，删除其目录。更改立即生效。使用渐进式披露添加支持文件Skills 与对话历史、其他 Skills 和你的请求共享 Claude 的上下文窗口。为了保持上下文集中，使用渐进式披露：将必要信息放在 SKILL.md 中，将详细的参考资料放在 Claude 仅在需要时读取的单独文件中。这种方法让你可以捆绑全面的文档、示例和脚本，而不会提前消耗上下文。Claude 仅在任务需要时加载其他文件。保持 SKILL.md 在 500 行以下以获得最佳性能。如果你的内容超过这个，将详细的参考资料分成单独的文件。示例：多文件 Skill 结构Claude 通过 SKILL.md 中的链接发现支持文件。以下示例显示了一个 Skill，其详细文档在单独的文件中，以及 Claude 可以执行而无需读取的实用脚本：my-skill/ ├── SKILL.md (required - overview and navigation) ├── reference.md (detailed API docs - loaded when needed) ├── examples.md (usage examples - loaded when needed) └── scripts/ └── helper.py (utility script - executed, not loaded)SKILL.md 文件引用这些支持文件，以便 Claude 知道它们存在：## Overview [Essential instructions here] ## Additional resources - For complete API details, see [reference.md](reference.md) - For usage examples, see [examples.md](examples.md) ## Utility scripts To validate input files, run the helper script. It checks for required fields and returns any validation errors: ```bash python scripts/helper.py input.txt ```保持引用一级深。直接从 SKILL.md 链接到参考文件。深层嵌套的引用（文件 A 链接到文件 B，文件 B 链接到文件 C）可能导致 Claude 部分读取文件。为零上下文执行捆绑实用脚本。 你的 Skill 目录中的脚本可以在不加载其内容到上下文的情况下执行。Claude 运行脚本，只有输出消耗令牌。这对以下情况很有用：复杂的验证逻辑，用散文描述会很冗长作为经过测试的代码比生成的代码更可靠的数据处理受益于跨使用一致性的操作在 SKILL.md 中，告诉 Claude 运行脚本而不是读取它：Run the validation script to check the form: python scripts/validate_form.py input.pdf有关构建 Skills 的完整指导，请参阅最佳实践指南。使用 allowed-tools 限制工具访问使用 allowed-tools 前置部分字段来限制当 Skill 活跃时 Claude 可以使用哪些工具。你可以将工具指定为逗号分隔的字符串或 YAML 列表：--- name: reading-files-safely description: Read files without making changes. Use when you need read-only file access. allowed-tools: Read, Grep, Glob ---或使用 YAML 风格的列表以获得更好的可读性：--- name: reading-files-safely description: Read files without making changes. Use when you need read-only file access. allowed-tools: - Read - Grep - Glob ---当此 Skill 活跃时，Claude 只能使用指定的工具（Read、Grep、Glob）而无需请求权限。这对以下情况很有用：不应修改文件的只读 Skills范围有限的 Skills：例如，仅数据分析，无文件写入你想限制功能的安全敏感工作流如果省略 allowed-tools，Skill 不会限制工具。Claude 使用其标准权限模型，可能会要求你批准工具使用。 allowed-tools 仅在 Claude Code 中的 Skills 支持。在分叉上下文中运行 Skills使用 context: fork 在具有自己对话历史的隔离子代理上下文中运行 Skill。这对于执行复杂的多步骤操作而不会使主对话混乱的 Skills 很有用：--- name: code-analysis description: Analyze code quality and generate detailed reports context: fork ---为 Skills 定义 HooksSkills 可以定义在 Skill 生命周期期间运行的 hooks。使用 hooks 字段指定 PreToolUse、PostToolUse 或 Stop 处理程序：--- name: secure-operations description: Perform operations with additional security checks hooks: PreToolUse: - matcher: "Bash" hooks: - type: command command: "./scripts/security-check.sh $TOOL_INPUT" once: true ---once: true 选项每个会话仅运行一次 hook。在第一次成功执行后，hook 被删除。在 Skill 中定义的 Hooks 限定于该 Skill 的执行，并在 Skill 完成时自动清理。有关完整的 hook 配置格式，请参阅Hooks。控制 Skill 可见性Skills 可以通过三种方式调用：手动调用：你在提示中输入 /skill-name程序调用：Claude 通过Skill 工具调用它自动发现：Claude 读取 Skill 的描述并在与对话相关时加载它user-invocable 字段仅控制手动调用。当设置为 false 时，Skill 从斜杠命令菜单中隐藏，但 Claude 仍然可以通过程序调用或自动发现它。要通过 Skill 工具阻止程序调用，请改用 disable-model-invocation: true。何时使用每个设置设置斜杠菜单Skill 工具自动发现用例user-invocable: true（默认）可见允许是你想让用户直接调用的 Skillsuser-invocable: false隐藏允许是Claude 可以使用但用户不应手动调用的 Skillsdisable-model-invocation: true可见阻止是你想让用户调用但 Claude 不能通过程序调用的 Skills示例：仅模型 Skill设置 user-invocable: false 以从斜杠菜单中隐藏 Skill，同时仍然允许 Claude 通过程序调用它：--- name: internal-review-standards description: Apply internal code review standards when reviewing pull requests user-invocable: false ---使用此设置，用户不会在 / 菜单中看到 Skill，但 Claude 仍然可以通过 Skill 工具调用它或根据上下文自动发现它。Skills 和子代理Skills 和子代理可以通过两种方式协同工作：给子代理访问 Skills子代理不会自动从主对话继承 Skills。要给自定义子代理访问特定 Skills，在子代理的 skills 字段中列出它们：# .claude/agents/code-reviewer.md --- name: code-reviewer description: Review code for quality and best practices skills: pr-review, security-check ---列出的 Skills 在子代理启动时加载到其上下文中。如果省略 skills 字段，则不会为该子代理预加载任何 Skills。 内置代理（Explore、Plan、general-purpose）无法访问你的 Skills。只有你在 .claude/agents/ 中定义的具有显式 skills 字段的自定义子代理可以使用 Skills。在子代理上下文中运行 Skill使用 context: fork 和 agent 在具有自己单独上下文的分叉子代理中运行 Skill。有关详细信息，请参阅在分叉上下文中运行 Skills。分发 Skills你可以通过多种方式共享 Skills：项目 Skills：将 .claude/skills/ 提交到版本控制。任何克隆存储库的人都会获得 Skills。插件：要在多个存储库中共享 Skills，在你的插件中创建一个 skills/ 目录，其中包含包含 SKILL.md 文件的 Skill 文件夹。通过插件市场分发。托管：管理员可以通过托管设置在组织范围内部署 Skills。有关托管 Skill 路径，请参阅Skills 存放在哪里。示例这些示例展示了常见的 Skill 模式，从最小的单文件 Skills 到具有支持文档和脚本的多文件 Skills。简单 Skill（单文件）最小的 Skill 仅需要一个带有前置部分和说明的 SKILL.md 文件。这个例子通过检查暂存的更改来帮助 Claude 生成提交消息：commit-helper/ └── SKILL.md--- name: generating-commit-messages description: Generates clear commit messages from git diffs. Use when writing commit messages or reviewing staged changes. --- # Generating Commit Messages ## Instructions 1. Run `git diff --staged` to see changes 2. I'll suggest a commit message with: - Summary under 50 characters - Detailed description - Affected components ## Best practices - Use present tense - Explain what and why, not how使用多个文件对于复杂的 Skills，使用渐进式披露来保持主 SKILL.md 集中，同时在支持文件中提供详细文档。这个 PDF 处理 Skill 包括参考文档、实用脚本，并使用 allowed-tools 将 Claude 限制为特定工具：pdf-processing/ ├── SKILL.md # Overview and quick start ├── FORMS.md # Form field mappings and filling instructions ├── REFERENCE.md # API details for pypdf and pdfplumber └── scripts/ ├── fill_form.py # Utility to populate form fields └── validate.py # Checks PDFs for required fieldsSKILL.md:--- name: pdf-processing description: Extract text, fill forms, merge PDFs. Use when working with PDF files, forms, or document extraction. Requires pypdf and pdfplumber packages. allowed-tools: Read, Bash(python:*) --- # PDF Processing ## Quick start Extract text: ```python import pdfplumber with pdfplumber.open("doc.pdf") as pdf: text = pdf.pages[0].extract_text() ``` For form filling, see [FORMS.md](FORMS.md). For detailed API reference, see [REFERENCE.md](REFERENCE.md). ## Requirements Packages must be installed in your environment: ```bash pip install pypdf pdfplumber ``` 如果你的 Skill 需要外部包，在描述中列出它们。在 Claude 可以使用它们之前，必须在你的环境中安装包。
Agent 设计模式：LLM 驱动下的多元思维范式与框架哲学
精准定位需求、匹配思维模式、发挥框架所长一、Agent 设计的 “百家争鸣”：从思维模式到框架分化在 LLM 驱动的 Agent 世界中，不存在 “放之四海而准” 的通用设计模式。Chain of Thought 的线性推理、ReAct 的 “知行合一”、Plan and Execute 的分层规划等认知框架，共同构成了 Agent 解决问题的 “思维模式库”。这些模式的落地差异，直接导致开发框架的路径分化 ——LangChain 聚焦链式推理的流程编排，LlamaIndex 深耕知识检索与整合，Dify 则主打人机协作的混合编排。业务场景的复杂性（如实时数据查询、多步逻辑推理、创意生成）决定了 Agent 必须 “量体裁衣”，而框架的多样性本质上是设计模式哲学的外在映射。二、认知框架解析：从单步推理到立体探索（一）线性推理范式：抽丝剥茧的思维显化1. Chain of Thought（思维链）：一步一释的逻辑展开[tabs][tab name="核心机制" active="true"]让模型在回答前，把推理过程一步步写出来。不是一口气给出答案，而是把整个推理过程展示出来。[/tab][tab name="适用场景"]问小王比小李大1岁，小张的年龄是小李的两倍。如果三个人的年龄加起来是41岁，问小王多大？思维链方式：假设小李的年龄是 ×，那么小王=×+3，小张=2X，总和=（x1）+×+（2X）=4×+ 1,4x+1=41，4X=38，×=10，所以小王=10+3=13。结果小王13岁。这种方式在逻辑推理、数值计算、逐步分析类问题里，会显得更稳健。[/tab][tab name="提出背景"]Google Research 在2022年发表的论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》[/tab][tab name="框架映射"]LangChain 的 “SequentialChain” 通过链式调用多个工具，实现思维链的工程化落地。[/tab][tab name="代码示例"]from langchain_openai import ChatOpenAI from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from langchain.chains import SimpleSequentialChain # 初始化LLM llm = ChatOpenAI(model="gpt-4-turbo", temperature=0) # 第一步：拆解问题（显式推理步骤） step1_prompt = PromptTemplate( input_variables=["question"], template="""请拆解解决以下数学问题的步骤，无需计算最终结果： 问题：{question} 推理步骤：""" ) step1_chain = LLMChain(llm=llm, prompt=step1_prompt, output_key="steps") # 第二步：执行计算（基于步骤推导结果） step2_prompt = PromptTemplate( input_variables=["steps"], template="""根据以下推理步骤，计算最终结果： 推理步骤：{steps} 最终答案（仅输出数字）：""" ) step2_chain = LLMChain(llm=llm, prompt=step2_prompt, output_key="result") # 串联链条 cot_chain = SimpleSequentialChain( chains=[step1_chain, step2_chain], verbose=True ) # 运行示例 result = cot_chain.run("计算(18+7)×(25-13)") print("最终结果：", result)输出效果：> Entering new SimpleSequentialChain chain... 推理步骤：1. 先计算括号内的加法：18+7 2. 再计算括号内的减法：25-13 3. 最后将两个结果相乘得到最终答案 最终答案（仅输出数字）：300 > Finished chain. 最终结果： 300[/tab][/tabs]2. Self-Ask（自问自答）：问题驱动的知识补全[tabs][tab name="核心机制" active="true"]让模型在回答时学会反思自己，把大问题拆成多个小问题，然后逐个回答。将复杂问题拆解为连续的子问题，通过 “提问 - 回答” 循环逐步逼近答案（如阅读理解中先问 “文章主旨是什么”，再问 “关键论据有哪些”）[/tab][tab name="适用场景"]信息碎片化任务（文献摘要生成、多跳问答），例如分析用户查询 “量子计算的商业落地挑战” 时，模型先自问 “当前量子计算技术瓶颈是什么”，再结合检索结果整合答案。[/tab][tab name="提出背景"]Microsoft Research 在2022年的研究工作《Self-Ask with Search》[/tab][tab name="框架映射"]LlamaIndex 的 “QuestionAnswerAgent” 通过递归查询知识库，实现自驱式问题分解。[/tab][tab name="代码示例"]代码示例（LangChain Self-Ask 带搜索）from langchain_openai import OpenAI from langchain.agents import initialize_agent, Tool from langchain.agents import AgentType from langchain.utilities import SerpAPIWrapper # 配置搜索工具（需申请SerpAPI密钥） os.environ["SERPAPI_API_KEY"] = "your-serpapi-key" search = SerpAPIWrapper() # 定义工具（仅保留搜索功能，用于子问题查询） tools = [ Tool( name="Intermediate Answer", func=search.run, description="当需要通过搜索获取信息时使用" ) ] # 初始化LLM和Agent llm = OpenAI(temperature=0, model="gpt-3.5-turbo-instruct") self_ask_agent = initialize_agent( tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True ) # 运行多跳问答示例 result = self_ask_agent.run( "2024年男子美网冠军的故乡在哪里？" ) print("最终答案：", result)输出效果：> Entering new AgentExecutor chain... Yes. Follow up: 2024年男子美网冠军是谁？ Intermediate answer: 卡洛斯·阿尔卡拉斯（Carlos Alcaraz） Follow up: 卡洛斯·阿尔卡拉斯的故乡在哪里？ Intermediate answer: 西班牙埃尔帕尔马（El Palmar, Spain） So the final answer is: 西班牙埃尔帕尔马（El Palmar, Spain） > 完成链。 最终答案： 西班牙埃尔帕尔马（El Palmar, Spain）[/tab][/tabs]（二）知行合一范式：推理与行动的动态闭环1. ReAct（推理 + 行动）：边思边动的交互探索[tabs][tab name="核心机制" active="true"]构建 “推理（Reason）- 行动（Act）- 观察（Observe）” 循环，模型根据实时反馈调整策略（如调用天气 API 后，结合降雨概率建议携带雨具）。ReAct比Cot、Self Ask更全能，原因在于它不仅是推理模式，还内建了与外部世界交互的闭环。Reason：模型的“内心独白”，用于分析任务目标、历史反馈和当前状态，明确下一步行动的逻辑依据；Act：模型与外部交互的“执行动作”，如调用搜索引擎、计算工具或控制设备；Observe：外部环境对行动的“客观反馈”，如搜索结果、计算答案，为下一轮推理提供真实数据支撑。[/tab][tab name="适用场景"]需外部工具介入的任务（实时数据查询、API 调用），典型案例：用户询问 “纽约到巴黎的直飞航班时间”，模型先推理需查询航空数据库，再调用 API 获取航班列表并筛选最优解。[/tab][tab name="提出背景"]Princeton 与 Google Research 在2022年论文 《ReAct: Synergizing Reasoning and Acting in Language Models》。[/tab][tab name="框架映射"]LangChain 的 “ReActAgent” 通过工具调用规范（如 “工具名称 + 参数” 格式），实现推理与行动的标准化衔接。[/tab][tab name="代码示例"]代码示例（ReAct 模式工具调用）from langchain_openai import ChatOpenAI from langchain.agents import create_react_agent, AgentExecutor from langchain_core.tools import Tool from langchain.prompts import PromptTemplate # 模拟航班查询工具 def query_flight(from_city, to_city): """模拟查询直飞航班信息的工具""" return { "航班号": "AF123", "出发时间": "2024-12-01 08:00", "到达时间": "2024-12-01 14:30", "飞行时长": "8小时30分钟" } # 定义工具列表 tools = [ Tool( name="FlightQuery", func=lambda x: query_flight(*x.split(",")), description="查询两个城市间的直飞航班，输入格式为'出发城市,到达城市'" ) ] # 自定义ReAct提示词 react_prompt = PromptTemplate( input_variables=["input", "agent_scratchpad", "tools", "tool_names"], template="""请按照以下步骤解决问题： 1. 分析问题是否需要调用工具（仅FlightQuery工具可查询航班） 2. 若需要，按格式调用工具：{tool_names}[输入内容] 3. 根据工具返回结果整理最终答案 可用工具：{tools} 问题：{input} 思考过程：{agent_scratchpad}""" ) # 初始化Agent llm = ChatOpenAI(model="gpt-4-turbo", temperature=0) agent = create_react_agent(llm, tools, react_prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # 运行示例 result = agent_executor.run("查询纽约到巴黎的直飞航班时间") print("最终答案：", result)输出效果：> Entering new AgentExecutor chain... 需要查询纽约到巴黎的直飞航班，调用FlightQuery工具。 FlightQuery[纽约,巴黎] 观察结果：{'航班号': 'AF123', '出发时间': '2024-12-01 08:00', '到达时间': '2024-12-01 14:30', '飞行时长': '8小时30分钟'} 整理结果：纽约到巴黎的直飞航班信息如下： - 航班号：AF123 - 出发时间：2024-12-01 08:00 - 到达时间：2024-12-01 14:30 - 飞行时长：8小时30分钟 > Finished chain. 最终答案： 纽约到巴黎的直飞航班信息如下：...[/tab][tab name="代码示例2"]工具封装遵循“基类定义接口+子类实现功能”的模式，确保所有工具调用方式统一。核心代码如下：from typing import Any, List class BaseTool: """工具基类，定义标准化接口""" def __init__(self, name: str, description: str): self.name = name # 工具名称（用于行动解析） self.description = description # 工具功能描述（用于模型理解） def run(self, params: Any) -> str: """核心执行方法，子类必须实现，返回结构化观察结果""" raise NotImplementedError("所有工具子类必须实现run方法") # 航班查询工具实现示例（调用模拟航班查询接口） class FlightSearchTool(BaseTool): def __init__(self): super().__init__( name="flight_search", description="用于查询指定条件的航班信息，参数格式为'出发地,目的地,日期,时段'，时段支持'上午/下午/晚上'" ) def run(self, params: str) -> str: """模拟航班查询工具执行逻辑，实际场景替换为真实航班API调用""" try: # 解析参数（出发地,目的地,日期,时段） dep, arr, date, time_period = params.split(',') # 模拟符合条件的航班搜索结果 flight_map = { "深圳,海南,明天,晚上": "符合条件航班列表：1. HU7089（深圳宝安→海口美兰，20:15-21:45，票价480元）；2. CZ6753（深圳宝安→三亚凤凰，21:30-23:05，票价620元）；3. MU2478（深圳宝安→海口美兰，19:40-21:10，票价550元）" } return flight_map.get(f"{dep},{arr},{date},{time_period}", f"未检索到{dep}到{arr}{date}{time_period}的相关航班信息") except Exception as e: returnf"航班查询工具调用失败：{str(e)[:50]}" # 航班预订工具实现示例（调用模拟航班预订接口） class FlightBookTool(BaseTool): def __init__(self): super().__init__( name="flight_book", description="用于预订指定航班，参数格式为'航班号,乘客姓名,身份证号'" ) def run(self, params: str) -> str: """模拟航班预订工具执行逻辑，实际场景替换为真实预订API调用""" try: # 解析参数（航班号,乘客姓名,身份证号） flight_no, name, id_card = params.split(',') # 模拟预订成功反馈 returnf"航班预订成功：航班号{flight_no}，乘客{name}（身份证号：{id_card[-4:]}），请携带有效证件提前2小时到机场办理登机手续" except Exception as e: returnf"航班预订失败：{str(e)[:50]}" 循环调度模块是ReAct的“中枢神经”，负责串联推理、行动、观察三个环节，核心代码如下class ContextManager: """上下文管理器：存储、裁剪与提取历史TAO轨迹""" def __init__(self, max_length: int = 4000): self.max_length = max_length # 上下文最大字符数 self.tao_trajectory = [] # 存储TAO三元组：[{"thought": "", "action": "", "observation": ""}] def add_tao(self, thought: str, action: str, observation: str) -> None: """添加TAO三元组并裁剪上下文""" self.tao_trajectory.append({ "thought": thought, "action": action, "observation": observation }) self._prune_trajectory() def _prune_trajectory(self) -> None: """裁剪超长轨迹：保留近期3轮+早期摘要""" trajectory_str = str(self.tao_trajectory) if len(trajectory_str) <= self.max_length: return # 保留近期3轮完整轨迹 recent_trajectory = self.tao_trajectory[-3:] if len(self.tao_trajectory) >=3else self.tao_trajectory # 生成早期轨迹摘要 early_actions = [item["action"] for item in self.tao_trajectory[:-3]] if len(self.tao_trajectory) >3else [] early_summary = f"早期行动：{', '.join(early_actions[:2])}... 关键结果：{[item['observation'][:30] for item in self.tao_trajectory[:-3] if '成功' in item['observation']][:1]}" # 重构上下文 self.tao_trajectory = [{"thought": "【早期轨迹摘要】", "action": "", "observation": early_summary}] + recent_trajectory def get_context_str(self) -> str: """生成模型可理解的上下文字符串""" ifnot self.tao_trajectory: return"无历史执行轨迹" return"\n".join([ f"步骤{idx+1}：思维：{item['thought']} | 行动：{item['action']} | 观察：{item['observation']}" for idx, item in enumerate(self.tao_trajectory) ]) def react_core_loop(task: str, tools: List[BaseTool], max_steps: int = 6) -> tuple[str, str]: """ReAct核心循环：控制TAO迭代流程，返回最终结果与执行轨迹""" # 初始化组件 context_manager = ContextManager() tool_map = {tool.name: tool for tool in tools} # 工具名称到实例的映射 # 提示词模板（含Few-shot示例，引导模型输出格式） prompt_template = """ 你是ReAct智能体，需通过"思维→行动→观察"循环完成任务，严格遵循以下规则： 1. 思维：分析任务目标与历史轨迹，说明下一步行动的逻辑依据； 2. 行动：仅使用提供的工具，格式为"工具名[参数]"，支持工具：{tool_descriptions}； 3. 观察：根据工具反馈调整后续策略，不可仅凭记忆回答。 示例： 任务：查询昨天从深圳到广州最便宜上午的航班 历史轨迹：无历史执行轨迹 思维：需获取昨天深圳到广州上午的航班信息，调用航班查询工具，参数为"深圳,广州,昨天,上午" 行动：flight_search[深圳,广州,昨天,上午] 观察：符合条件航班列表：1. CZ3201（深圳宝安→广州白云，08:30-09:10，票价230元）；2. HU7125（深圳宝安→广州白云，09:40-10:20，票价280元） 思维：已获取航班列表，需筛选最便宜的航班（CZ3201，230元），调用航班预订工具完成预订 行动：flight_book[CZ3201,张三,440301199001011234] 观察：航班预订成功：航班号CZ3201，乘客张三（身份证号：1234），请携带有效证件提前2小时到机场办理登机手续 思维：已完成航班查询与预订任务，提交结果 行动：finish[昨天深圳到广州最便宜上午航班为CZ3201（08:30-09:10，票价230元），已完成预订，乘客张三] 当前任务：{task} 历史轨迹：{context} 请输出当前步骤的思维和行动（仅输出思维和行动，无其他内容）： 思维： 行动： """ # 循环迭代 for step in range(max_steps): # 1. 构建提示词，调用LLM生成思维与行动（实际场景替换为真实LLM API） tool_descriptions = "\n".join([f"- {name}：{tool.description}"for name, tool in tool_map.items()]) prompt = prompt_template.format( tool_descriptions=tool_descriptions, task=task, context=context_manager.get_context_str() ).strip() # 模拟LLM输出（实际场景替换为OpenAI API等调用） # 此处根据任务逻辑生成模拟输出，真实场景由LLM自主生成 if step == 0: llm_output = """思维：当前任务是查询明天从深圳到海南的航班，选最便宜、航班时间在晚上的那班并预订，无历史数据。需先调用航班查询工具，参数为"深圳,海南,明天,晚上"，获取符合条件的航班列表 行动：flight_search[深圳,海南,明天,晚上]""" elif step == 1: llm_output = """思维：已获取明天深圳到海南晚上的航班列表，从观察结果可知最便宜的是HU7089（票价480元）。下一步需调用航班预订工具，参数包含航班号HU7089、乘客信息（假设乘客为李四，身份证号440301199505056789） 行动：flight_book[HU7089,李四,440301199505056789]""" elif step == 2: llm_output = """思维：已完成最便宜晚上航班的查询与预订，观察结果显示预订成功，所有任务目标均达成，可提交最终结果 行动：finish[明天从深圳到海南最便宜的晚上航班为HU7089（深圳宝安→海口美兰，20:15-21:45，票价480元），已完成预订，乘客李四（身份证号：6789）]""" else: llm_output = """思维：任务已完成，无需进一步行动 行动：finish[任务已完成]""" # 2. 解析思维与行动（真实场景需增加格式校验） thought = llm_output.split("思维：")[1].split("行动：")[0].strip() action = llm_output.split("行动：")[1].strip() # 3. 执行行动并获取观察结果 if action.startswith("finish["): # 任务完成，提取结果 result = action[len("finish["):-1].strip() return result, context_manager.get_context_str() elif action.startswith(tuple(tool_map.keys())): # 解析工具类型与参数 tool_name = next(name for name in tool_map.keys() if action.startswith(name)) param_str = action[len(tool_name)+1:-1].strip() # 调用工具 observation = tool_map[tool_name].run(param_str) else: # 无效行动 observation = f"无效行动：{action}，支持的工具为{list(tool_map.keys())}" # 4. 更新上下文 context_manager.add_tao(thought, action, observation) print(f"步骤{step+1}：思维：{thought} | 行动：{action} | 观察：{observation}") # 超时终止 returnf"任务未完成（已达最大步数{max_steps}）", context_manager.get_context_str() # 调用示例 if __name__ == "__main__": # 初始化工具 tools = [FlightSearchTool(), FlightBookTool()] # 定义任务 task = "查询明天从深圳到海南的航班，选最便宜、航班时间在晚上的那班并预订" # 运行ReAct循环 final_result, trajectory = react_core_loop(task, tools) # 输出结果 print("\n最终结果：", final_result) print("\n完整执行轨迹：", trajectory) [/tab][/tabs]2. Plan and Execute（计划与执行）：先谋后动的分层协作[tabs][tab name="核心机制" active="true"]分阶段处理任务 —— 规划阶段生成包含子任务的详细计划（如项目开发的需求分析、后端开发、测试部署三阶段），执行阶段按序完成每个子任务并整合结果。[/tab][tab name="适用场景"]复杂多步骤任务（软件开发、科研分析），例如解决 “设计一个电商用户认证系统” 时，规划器先拆解为 “数据库模型设计”“API 接口开发”“前端组件实现”，执行器再逐一落地。[/tab][tab name="提出背景"]出现在 2023年前后的 Agent应用开发框架实践（如 LangChain 社区）[/tab][tab name="框架映射"]Dify 的 “Workflow Orchestration” 支持可视化规划编排，结合人机协同节点实现动态调整。[/tab][tab name="代码示例"]代码示例（LangChain Plan-Execute 实现）from langchain_openai import ChatOpenAI from langchain.chains import LLMChain from langchain.prompts import PromptTemplate # 初始化LLM llm = ChatOpenAI(model="gpt-4-turbo", temperature=0.3) # 1. 规划器：拆解任务为子步骤 planner_prompt = PromptTemplate( input_variables=["task"], template="""将以下复杂任务拆解为3-5个可执行的子任务，按顺序排列： 任务：{task} 子任务列表（编号+描述）：""" ) planner_chain = LLMChain(llm=llm, prompt=planner_prompt, output_key="sub_tasks") # 2. 执行器：完成单个子任务 executor_prompt = PromptTemplate( input_variables=["sub_task"], template="""完成以下子任务，输出具体执行结果： 子任务：{sub_task} 执行结果：""" ) executor_chain = LLMChain(llm=llm, prompt=executor_prompt, output_key="result") # 3. 整合器：合并所有子任务结果 integrator_prompt = PromptTemplate( input_variables=["task", "all_results"], template="""根据以下子任务执行结果，整合为完整的任务解决方案： 原始任务：{task} 子任务执行结果： {all_results} 完整解决方案：""" ) integrator_chain = LLMChain(llm=llm, prompt=integrator_prompt, output_key="final_result") # 执行流程 def plan_and_execute(task): # 生成计划 plan = planner_chain.run(task) print("任务分解：\n", plan) # 执行每个子任务 sub_tasks = [line.strip() for line in plan.split("\n") if line.strip().startswith(("1.", "2.", "3.", "4.", "5."))] all_results = [] for i, sub_task in enumerate(sub_tasks, 1): result = executor_chain.run(sub_task) all_results.append(f"子任务{i}：{sub_task}\n结果：{result}") print(f"\n子任务{i}执行完成：\n", result) # 整合结果 final_result = integrator_chain.run(task=task, all_results="\n\n".join(all_results)) return final_result # 运行示例 final = plan_and_execute("设计一个电商用户认证系统") print("\n最终解决方案：\n", final)输出效果：任务分解： 1. 设计用户数据库模型（包含用户名、密码哈希、手机号、邮箱等字段） 2. 实现手机号+验证码登录接口 3. 实现密码重置功能（通过邮箱验证） 4. 设计用户权限分级机制（普通用户/管理员） 5. 增加登录异常检测（异地登录提醒、多次失败锁定） 子任务1执行完成： 数据库模型采用MySQL，用户表（user）字段设计： - id: INT(11) 主键自增 - username: VARCHAR(50) 唯一用户名 - password_hash: VARCHAR(255) bcrypt加密存储 - phone: VARCHAR(20) 唯一手机号 - email: VARCHAR(100) 唯一邮箱 - role: ENUM('user', 'admin') 角色标识 - created_at: DATETIME 创建时间 - updated_at: DATETIME 更新时间 ...（其他子任务执行结果） 最终解决方案： 电商用户认证系统设计方案如下： 一、数据库设计（子任务1结果） ... 二、核心功能实现（子任务2-5结果） ...[/tab][/tabs]（三）立体探索范式：从单一路径到多维搜索1. Tree of Thoughts（ToT，树状思维）：分支探索的最优路径筛选[tabs][tab name="核心机制" active="true"]生成多个推理分支（如创意写作的不同情节走向、数学题的多种解法），通过自评估（如评分投票）选择最优路径继续探索，支持回溯修正（如发现分支矛盾时返回前序节点）。[/tab][tab name="适用场景"]需多可能性探索的任务（策略规划、创意生成），例如 “24 点游戏” 中，模型同时计算 “(6-2)×(3+3)” 和 “3×8×(2-1)” 等多条路径，评估后选择有效解。[/tab][tab name="提出背景"]Princeton 和 DeepMind 在2023年的论文《Tree of Thoughts: Deliberate problem Solving with Large Language Models》。[/tab][tab name="框架映射"]实验性框架如 “ToT-Hub” 提供树状结构管理工具，支持深度优先 / 广度优先搜索策略。[/tab][tab name="代码示例"]代码示例（简化版 ToT 实现 24 点游戏）from langchain_openai import ChatOpenAI import itertools llm = ChatOpenAI(model="gpt-4-turbo", temperature=0.5) def generate_branches(numbers): """生成所有可能的运算分支""" branches = [] # 生成所有数字排列 for nums in itertools.permutations(numbers, 2): # 生成所有运算符组合 for op in ["+", "-", "*", "/"]: if op == "/" and nums[1] == 0: continue # 避免除零 # 计算中间结果 try: result = eval(f"{nums[0]}{op}{nums[1]}") remaining = [n for n in numbers if n not in nums] + [result] branches.append({ "step": f"{nums[0]}{op}{nums[1]}={result}", "remaining": remaining, "path": [f"{nums[0]}{op}{nums[1]}"] }) except: continue return branches def evaluate_branch(branch): """评估分支是否接近24点""" score = 0 for num in branch["remaining"]: if 20 <= num <= 28: score += 5 # 接近24加分 elif 10 <= num <= 35: score += 3 return score def tot_24_game(numbers): """Tree of Thoughts求解24点""" current_branches = generate_branches(numbers) for _ in range(2): # 最多探索2层 # 评估并筛选前3个最优分支 current_branches = sorted(current_branches, key=evaluate_branch, reverse=True)[:3] next_branches = [] for branch in current_branches: if len(branch["remaining"]) == 1: # 只剩一个数字，检查是否为24 if abs(branch["remaining"][0] - 24) < 1e-6: return " → ".join(branch["path"]) + "=24" continue # 继续生成下一层分支 new_branches = generate_branches(branch["remaining"]) for new_branch in new_branches: new_branch["path"] = branch["path"] + [new_branch["step"].split("=")[0]] next_branches.append(new_branch) current_branches = next_branches # 若未找到精确解，返回最优尝试 best_branch = max(current_branches, key=evaluate_branch) return " → ".join(best_branch["path"]) + f"={best_branch['remaining'][0]}（接近24）" # 运行示例 result = tot_24_game([3, 6, 2, 8]) print("24点解法：", result)输出效果：24点解法： 3+6 → 9×2 → 18+8=26（接近24） # 或找到精确解时输出：6-2 →4×3 →12×2=24[/tab][/tabs]2. Reflexion / Iterative Refinement（反思与迭代优化）：自我批判的持续进化[tabs][tab name="核心机制" active="true"]生成初步答案后，通过自我评估（如检查逻辑漏洞、事实准确性）触发迭代优化（如代码生成后自动检测语法错误并修正）。[/tab][tab name="适用场景"]让 Agent 写一段 Python 代码，如果第一次运行报错，它会读报错信息，反思“函数参数写错了”，然后自动修正并重试。适合代码生成、流程执行类场景。[/tab][tab name="提出背景"]2023年论文 《Reflexion: Language Agents with Verbal ReinforcementLearning》。[/tab][tab name="框架映射"]LlamaIndex 的 “CritiqueEngine” 结合外部知识库，实现对输出的多维度验证。[/tab][tab name="代码示例"]代码示例（Reflexion 迭代优化代码生成）from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate class ReflexionAgent: def __init__(self, model="gpt-4-turbo", max_attempts=3): self.llm = ChatOpenAI(model=model, temperature=0) self.max_attempts = max_attempts self.reflections = [] # 反思日志 def _executor(self, task): """执行任务生成初始结果""" prompt = ChatPromptTemplate.from_messages([ ("system", "你是Python开发专家，生成简洁可运行的代码"), ("user", f"任务：{task}\n之前的反思：{self.reflections[-1] if self.reflections else '无'}") ]) return prompt | self.llm def _reflector(self, task, output, error=None): """反思失败原因""" prompt = ChatPromptTemplate.from_messages([ ("system", "分析代码问题，仅输出具体改进点（1-2条）"), ("user", f"任务：{task}\n生成的代码：{output}\n错误信息：{error or '无'}") ]) reflection = (prompt | self.llm).invoke({}).content self.reflections.append(reflection) return reflection def run(self, task): for attempt in range(self.max_attempts): print(f"\n=== 第{attempt+1}次尝试 ===") # 生成代码 chain = self._executor(task) output = chain.invoke({}).content print("生成的代码：\n", output) # 尝试运行代码（模拟执行） try: exec(output) # 实际场景需在沙箱中执行 print("代码执行成功！") return output except Exception as e: error_msg = str(e)[:100] print(f"执行失败：{error_msg}") # 反思并优化 reflection = self._reflector(task, output, error_msg) print("反思改进：", reflection) return f"经过{self.max_attempts}次优化仍未成功，最终代码：\n{output}" # 运行示例 agent = ReflexionAgent(max_attempts=2) result = agent.run("编写Python函数，计算列表中所有偶数的平方和") print("\n最终结果：\n", result)输出效果：=== 第1次尝试 === 生成的代码： def sum_even_squares(lst): total = 0 for num in lst: if num % 2 == 0: total += num^2 return total 执行失败：unsupported operand type(s) for ^: 'int' and 'int' 反思改进：1. Python中平方运算符是**而非^，^是按位异或；2. 需添加参数类型检查 === 第2次尝试 === 生成的代码： def sum_even_squares(lst): total = 0 for num in lst: if isinstance(num, int) and num % 2 == 0: total += num **2 return total 代码执行成功！ 最终结果： def sum_even_squares(lst): total = 0 for num in lst: if isinstance(num, int) and num % 2 == 0: total += num **2 return total[/tab][/tabs]（四）协作分工范式：从个体智能到群体协同Role-playing Agents（角色扮演式智能体）：多主体协作的分工进化[tabs][tab name="核心机制" active="true"]通过定义不同角色（如 “决策者”“执行者”“审查者”），模拟人类团队分工（如项目管理中，策划 Agent 制定方案，开发 Agent 实现功能，测试 Agent 验证效果）。[/tab][tab name="适用场景"]场景例子：一个软件开发任务里，有产品经理 Agent 写需求文档，程序员 Agent 写代码，测试 Agent写测试用例。它们像团队一样协作。适合复杂系统开发或跨职能协同。[/tab][tab name="提出背景"]源自 AutoGPT、ChatDev、CAMEL 等社区项目。[/tab][tab name="框架映射"]Dify 的 “Multi-Agent Orchestration” 支持角色间状态共享与消息传递，实现流程化协作。[/tab][tab name="代码示例"]代码示例（AutoGen 多智能体协作）import autogen from autogen import AssistantAgent, UserProxyAgent # 配置LLM config_list = [ { "model": "gpt-4-turbo", "api_key": os.environ["OPENAI_API_KEY"], } ] # 定义角色Agent product_manager = AssistantAgent( name="产品经理", system_message="""你负责需求分析和方案设计，明确电商网站的核心功能模块， 输出详细的需求文档（包含用户故事、功能清单、优先级）""", llm_config={"config_list": config_list} ) developer = AssistantAgent( name="开发者", system_message="""你负责技术实现，根据需求文档设计技术架构， 输出后端API设计和数据库模型（使用Python+MySQL技术栈）""", llm_config={"config_list": config_list} ) tester = AssistantAgent( name="测试工程师", system_message="""你负责测试用例设计，根据需求文档和技术方案， 输出功能测试用例和接口测试用例（包含输入、预期输出、优先级）""", llm_config={"config_list": config_list} ) # 定义用户代理（协调者） user_proxy = UserProxyAgent( name="用户", system_message="协调产品、开发、测试团队完成电商网站需求落地", human_input_mode="NEVER", # 无需人工干预 max_consecutive_auto_reply=10 ) # 定义协作流程 groupchat = autogen.GroupChat( agents=[user_proxy, product_manager, developer, tester], messages=[], max_round=10, speaker_selection_method="auto" # 自动选择发言者 ) manager = autogen.GroupChatManager( groupchat=groupchat, llm_config={"config_list": config_list} ) # 启动协作 user_proxy.initiate_chat( manager, message="请团队协作完成小型电商网站的需求设计、技术实现和测试方案" )输出效果：用户：请团队协作完成小型电商网站的需求设计、技术实现和测试方案 产品经理： # 电商网站需求文档 ## 核心功能模块 1. 商品管理（上架、编辑、分类）- 优先级P0 2. 用户管理（注册、登录、个人中心）- P0 3. 购物车（添加、修改、删除）- P1 ... 开发者： # 技术方案设计 ## 后端架构 - 框架：FastAPI - 数据库：MySQL 8.0 ## API设计 1. 商品接口：GET /api/products（列表）、POST /api/products（创建） ... ## 数据库模型 商品表（products）：id, name, price, category_id, stock... 测试工程师： # 测试用例设计 ## 商品管理功能测试 | 用例ID | 输入 | 预期输出 | 优先级 | |--------|------|----------|--------| | TC001 | 上架名称为空的商品 | 返回400错误 | P0 | ... ## 接口测试用例 GET /api/products： - 输入：?page=1&size=10 - 预期：返回200，包含商品列表和分页信息[/tab][/tabs]三、框架选择的 “生态法则”：定位决定生存不同框架的设计哲学，本质是对 “工具依赖度”“推理透明度”“探索深度” 的差异化取舍：工具驱动型（如 ReAct、函数调用）：依赖外部 API / 数据库，适合实时数据任务（如金融行情分析）；推理解释型（如 CoT、Self-Ask）：侧重过程显化，适合教育、客服等需用户信任的场景；探索优化型（如 ToT、Reflexion）：聚焦多路径搜索与迭代，适合创意生成、复杂决策。正如没有 “万能钥匙”，Agent 框架的价值在于 “精准定位”——LangChain 凭借链式推理的灵活性成为通用首选，LlamaIndex 以知识检索优势扎根垂直领域，Dify 则通过人机混合编排抢占协作场景。只要能清晰回答 “解决什么问题、服务哪类用户、如何差异化赋能”，每个框架都能在 Agent 生态中找到属于自己的 “生存空间”。四、结语：在多样性中寻找平衡Agent 设计模式的 “百花齐放”，既是 LLM 能力边界的自然延伸，也是复杂场景的必然要求。从线性推理到树状探索，从单 Agent 执行到多角色协作，每个框架都是对 “智能体该如何思考” 的独特解答。对于开发者而言，关键不是追逐 “最优框架”，而是理解每种模式的思维内核 —— 当链状推理需要工具加持时选择 ReAct，当多步规划需要人机协同时有 Dify，当知识检索需要深度整合时用 LlamaIndex。
🚀 掌握这些提示框架，让你与AI对话效率翻倍！✨
你是不是经常觉得和AI聊天时，它总是不太“懂你”？或者给出的回答不够精准、不够有深度？别担心，今天我就来带你掌握几种超实用的提示词框架，让你轻松驾驭大模型，对话质量直线上升！🎯🤔 为什么我们需要提示框架？和AI交流，就像和一位聪明但需要引导的伙伴合作。如果你问得模糊，它可能答得随意；如果你问得清晰，它就能回应得精彩。 提示框架就是一套“提问模板”，帮你结构化表达需求，让AI更容易理解你的意图，输出更符合你期待的内容。📚 四大提示框架详解 + 实战案例1. CRISPE 框架 🧠适用于需要AI扮演特定角色、完成复杂任务的场景。角色：明确AI的身份，例如“教育者”、“翻译官”或“职业顾问”。背景：交代情境，帮助AI理解上下文。任务：清晰说明你要它做什么。格式：设定回复的风格、长度、结构等。实验：可要求AI给出多个版本供你选择。💡 案例：你是一位资深科技博主（角色），正在撰写一篇面向初学者的AI入门文章（背景）。请用通俗易懂的语言，解释什么是机器学习（任务）。文章结构请包括：定义、常见类型、一个生活化例子（格式）。如果能提供两个不同风格的开头供我选择更好（实验）。2. BROKE 框架 📝适合内容创作、文案撰写等需要明确目标和成果的任务。背景：设定任务发生的场景。角色：指定AI的专业身份。目标：说明核心任务。关键结果：列出回答必须包含的要素。改进：AI回复后，可提出优化方向。💡 案例：背景：你正在为一家健康食品初创公司撰写社交媒体推文。 角色：作为品牌文案策划。 目标：写一条推广新款燕麦产品的推文。 关键结果：突出“无添加糖”、“高纤维”、“早餐便捷”三大卖点，语气年轻活泼，带一个表情符号。 改进：可以建议“加入用户证言”或“增加互动提问”。3. ICIO 框架 🛠️适用于处理具体输入数据、要求明确输出的任务，如翻译、摘要、格式转换等。任务：直接说明要做什么。背景：补充任务的相关信息。输入数据：提供AI需要处理的原文、数据等。输出格式：明确回答的形式与风格。💡 案例：任务：将以下英文邮件翻译成中文。 背景：这是一封发给客户的正式项目更新邮件。 输入数据：“Dear team, the project milestone has been achieved ahead of schedule. We will proceed to the next phase next Monday.” 输出格式：使用商务中文，保持礼貌正式，不要添加额外解释。4. CoT 思维链框架 🔗适合需要逻辑推理、分步分析的问题，引导AI“一步步思考”。Few-Shot CoT：给出几个包含推理步骤的例子，AI会模仿这种思考方式。Zero-Shot CoT：只需在提问后加一句“请一步步思考”或“Let‘s think step by step”，AI就会自动展开推理。💡 案例：问题：“如果小明每天存10元，存了30天后，他用一半的钱买书，剩下的钱又每天花5元，能花几天？” 提示：“请一步步思考。” AI会先计算总金额，再算买书后剩余金额，最后算能花几天，并列出每一步。✅ 通用交互小贴士除了框架，这些技巧也能大幅提升对话效果哦：🧩 长文分段输出：比起一次性生成长篇内容，分多次请求输出，质量往往更稳定。🔗 符号分隔信息：用“---”、“===”或序号区分不同部分，AI更容易解析。🎓 给出示例：直接展示你想要的格式或风格，AI模仿能力很强！🧠 任务拆解：复杂任务拆成几个步骤，逐步引导，结果更可控。📏 明确限制：指定字数、格式、风格、语言难度等，避免AI“自由发挥”。🎨 总结：如何选择框架？需要AI扮演角色 → 用 CRISPE要写文案、内容 → 用 BROKE有具体输入、输出格式要求 → 用 ICIO需要逻辑推理、分步解答 → 用 CoT当然，也可以混合使用这些框架，比如在CRISPE中加入CoT的推理步骤，让AI既扮演角色又理性分析！
版本1：详细判断型DETAILED_JUDGE_PROMPT = """ 你是一个专业的客服质检专家，专门负责检测客服的回复质量。【任务】 判断客服的回复是否属于"冗余或机械确认"。【定义】 "冗余或机械确认"指：当用户提问清晰明确时，客服采用简单重复用户问题的方式来确认，而没有提供额外价值、信息或引导。【判断标准】用户提问是否清晰明确？明确：包含具体需求、动作、对象（如"帮我解绑实名"）不明确：包含疑问词、模糊表达（如"这个怎么办？"）客服回复是否属于简单重复？是：客服只是把用户问题换个说法重复一遍否：客服提供了额外信息、解决方案、引导或确认了具体细节是否有必要进行这种确认？必要：用户问题存在歧义、需要澄清细节不必要：用户问题已经非常清晰明确【上下文信息】 会话开始时间：{session_start_time} 当前对话轮次：第{round_number}轮最近3轮对话历史： {recent_dialogue_history}【待判断的消息】 用户消息：{user_message} 客服回复：{assistant_message}【输出格式】 请严格按照以下JSON格式输出： {{ "is_violation": true/false, "reason": "详细的判断理由，至少50字", "confidence": 0.0-1.0的置信度, "suggestion": "改进建议（如果违规）"}}请开始判断： """版本2：思维链推理型CHAIN_OF_THOUGHT_PROMPT = """ 你是一个严谨的客服质检专家。请按照以下步骤进行推理：【步骤1：分析用户提问】 用户提问："{user_message}"是否清晰明确？请分析：是否有具体需求？是否有明确动作？是否有具体对象？结论：清晰明确 / 不够明确【步骤2：分析客服回复】 客服回复："{assistant_message}"主要内容和意图是什么？是否提供了额外信息或价值？与用户提问的关系是什么？【步骤3：判断是否属于冗余确认】 对比分析：客服是否只是简单重复用户问题？这种确认是否有必要？是否有更好的回复方式？【步骤4：综合判断】 基于以上分析，给出最终判断：最终判断：属于冗余确认 / 不属于冗余确认 理由：{至少100字的详细分析} 置信度：{0.0-1.0}【步骤5：输出】 请输出JSON格式： {{ "judgment": "属于冗余确认" 或 "不属于冗余确认", "reasoning": "完整的推理过程", "confidence": 0.95, "improvement": "改进建议（如果违规）"}} """版本3：多维度评估型MULTI_DIMENSIONAL_PROMPT = """ 作为客服质检专家，请从以下5个维度评估客服回复：【维度1：信息增量（0-10分）】 客服回复相比用户提问增加了多少新信息？0-3分：几乎没有新信息，简单重复4-6分：有少量新信息7-10分：提供了有价值的额外信息【维度2：确认必要性（0-10分）】 这种确认是否必要？0-3分：完全不必要，用户问题已非常清晰4-6分：有一定必要性7-10分：非常必要，需要澄清模糊点【维度3：回复效率（0-10分）】 回复是否简洁高效？0-3分：冗余啰嗦，可以更简洁4-6分：适中7-10分：非常简洁高效【维度4：服务意识（0-10分）】 是否体现主动服务意识？0-3分：被动机械，缺乏服务意识4-6分：基本满足要求7-10分：主动周到，体现专业服务【维度5：用户体验（0-10分）】 对用户体验的影响？0-3分：负面体验，让用户感到不被重视4-6分：中性体验7-10分：正面体验，让用户感到被重视【评估数据】 用户消息：{user_message} 客服回复：{assistant_message} 对话历史：{dialogue_history}【输出要求】 请输出JSON格式的详细评估： {{ "dimension_scores": {{ "information_increment": 分数, "confirmation_necessity": 分数, "reply_efficiency": 分数, "service_awareness": 分数, "user_experience": 分数 }}, "total_score": 总分（0-50）, "is_violation": true/false（总分<25为违规）, "detailed_analysis": "每个维度的详细分析", "recommendation": "具体的改进建议"}} """
从 0 到 1 在 CPU 上训练可推理可演示的小参数中文GPT
clearwind-tse/gpt_encode_teacher-cn-mini了解 GPT 的核心原理：分词 → 批处理 → 前向 → 损失 → 反向 → 优化 → 保存 → 推理（完整链路）掌握高效小模型技术：RMSNorm、RoPE、权重共享、短序列、小词表、量化仅用 CPU 训练：控制模型/数据规模、梯度累积、学习率预热与退火、禁用无关耗时特性可用答案保障：目标对齐（忽略前缀）、推理首步约束与后处理、停止词、提示词规范化代码结构src/model.py：GPT 核心（Embedding/自注意力/前馈/RMSNorm/RoPE/权重共享）src/data.py：分词器加载、指令和 LM 数据处理、批处理与目标构造src/train.py：CPU 训练主循环、评估、保存与动态量化、耗时统计src/infer.py：推理 CLI（温度、top-k、top-p、重复惩罚、停止词、输出清理）src/build_tokenizer.py：构建 HF ByteLevel BPE 中文分词器（带解码器，避免乱码）config.yaml：统一管理模型、训练、数据、分词器与保存路径data/*.jsonl：教学数据（{"prompt": "...", "completion": "..."}）使用技术模型结构：Decoder-only Transformer（因果自注意力）归一化：RMSNorm（简洁高效）位置编码：RoPE（相对位置，计算高效）前馈：SiLU（现代 LLM 常用）权重共享：词嵌入与输出层共享，降参数且表示一致训练：AdamW、学习率线性预热+余弦退火、梯度裁剪数据与分词：外置jsonl+HF ByteLevel BPE（显式设置 ByteLevel 解码器，避免乱码）推理：温度/top-k/top-p 采样、重复惩罚、停止词、输出清理、提示规范化量化：导出动态量化权重以加速 CPU 推理如何仅用 CPU 训练小模型+短序列：n_layer=4, n_head=4, n_embd=256, seq_len=128小词表：HF ByteLevel BPE（带解码器）梯度累积：batch_size=16, micro_batch=4（有效批 64）学习率策略：线性预热 10%+余弦退火资源控制：torch.set_num_threads(os.cpu_count())，DataLoader 禁用多进程（macOS 下更稳）训练结束导出量化权重，演示更流畅GPT 训练是如何实现的因果自注意力：下三角 mask 确保只看历史（src/model.py:98）Teacher Forcing：输入拼接“用户/prompt + 助手 + 答案”，仅对答案段计算损失（src/data.py:24–31）目标对齐：忽略区间为len(prefix)-1，确保第一个答案 token 参与训练（src/data.py:28–31）损失函数：CrossEntropyLoss(ignore_index=-100)（src/train.py:50）如何保证“回答可用”分词器解码器：HF BPE 设置 ByteLevel 解码器，彻底消除中文乱码（src/build_tokenizer.py:6–8）目标对齐修复：忽略len(prefix)-1，避免答案错位（src/data.py:28–31）推理约束：首步屏蔽PAD/BOS/UNK，前若干步屏蔽EOS，避免空答（src/infer.py:41–50, 68–73）开头清理：剔除首字符标点与空白（src/infer.py:26–30, 82–83）提示词规范化：去中文空格（src/infer.py:35–37）停止词/重复惩罚：控制尾部冗余与重复（src/infer.py:68–73）训练耗时与评估：日志实时打印eval loss与elapsed，课时内可观测质量（src/train.py:71–82）step by step1. 安装依赖python -m pip install -r requirements.txt2. 构建中文分词器（HF ByteLevel BPE）python -m src.build_tokenizer3. 配置核对config.yaml 中：data.train_path: data/train.jsonldata.val_path: data/val.jsonltokenizer.type: hf_tokenizerstokenizer.path: tokenizer/tokenizer.jsontraining.max_steps: 1500–2000（课堂机器允许的话）4. 训练（仅 CPU）python -m src.train观察日志：每eval_interval步打印eval loss与累计elapsed Xs结束后保存：checkpoints/last.pt、checkpoints/quantized.pt、checkpoints/train_time.txt5. 推理验证（两条固定问题）# Question1 python -m src.infer --prompt "什么是注意力机制？" --ckpt checkpoints/last.pt --temperature 0.0 --show_label # Question2 python -m src.infer --prompt "解释蒸馏水与纯水区别？" --ckpt checkpoints/last.pt --temperature 0.0 --show_label期望结果（示例）：Q1：注意力机制通过分配权重让模型关注关键位置，从而更好地理解序列中的关系。Q2：蒸馏水是通过蒸馏获得的水，去除了大部分杂质；纯水是指杂质含量极低的水，制备方式可以是蒸馏、反渗透等。若出现“串联两段”或冗长，可加入停止词：python -m src.infer --prompt "什么是注意力机制？" --stop_strings "。" "；" "\n" --temperature 0.0 --show_label6.（可选）量化权重推理python -m src.infer --prompt "什么是注意力机制？" --ckpt checkpoints/quantized.pt --temperature 0.0 --show_label核心代码参考（行号）因果 mask 与前向（src/model.py:95–103）RoPE 相对位置（src/model.py:18–31）自注意力前向（src/model.py:41–58）指令目标构造与忽略前缀（src/data.py:24–31）训练主循环（src/train.py:56–80）推理生成与采样管线（src/infer.py:32–83）ByteLevel 解码器设置（src/build_tokenizer.py:6–8）说明：src/model.py核心约百行即可完整呈现 GPT 最小闭环；其余文件各自职责清晰，便于教学与修改。核心代码解析（从架构 → 流程 → 方法级）整体架构src/model.py：定义 GPT 的模块化组件（RMSNorm、RoPE、自注意力、前馈、残差与权重共享）src/data.py：将{"prompt","completion"}样本转换为模型输入与训练目标（teacher forcing）src/train.py：CPU 训练主循环、评估与保存（含动态量化与耗时统计）src/infer.py：命令行推理与采样策略（含输出清理与停止词）src/tokenizer.py/src/build_tokenizer.py：HF ByteLevel BPE 分词器加载与构建（含 ByteLevel 解码器）训练流程（管线）加载配置与分词器（src/train.py:21–26，src/tokenizer.py:20–39）构建数据集与 DataLoader（src/data.py:66–70，src/train.py:39–40）前向与损失（src/train.py:60–62）→ 反向与梯度累积（src/train.py:62–68）→ 优化与调度（src/train.py:65–69）评估与保存（src/train.py:71–80）→ 导出量化（src/train.py:81–82）模型方法级解析归一化：RMSNorm.forward（src/model.py:13–16）用均方根缩放激活，结构简洁、计算高效位置编码：rope（src/model.py:18–31）将相对位置信息旋转注入 Q/K，提高位置泛化自注意力：SelfAttention.forward（src/model.py:41–58）Q/K/V 分解 → 注意力权重 → 输出投影；含因果 mask 与 Dropout残差块：Block.forward（src/model.py:81–84）注意力与前馈的残差堆叠，RMSNorm 在前模型前向：GPT.forward（src/model.py:95–103）嵌入 → 堆叠 Block→ 归一化 →LM Head（共享权重）数据与目标（方法级）指令样本构造：InstructDataset.__init__（src/data.py:10–35）拼接用户:prompt\n助手:为前缀，答案接在后；截断至seq_len目标构造：tar = ids[1:] + [EOS]（src/data.py:24–27）并忽略len(prefix)-1位置（src/data.py:28–31），只对答案段计算损失批处理：collate（src/data.py:54–64）按seq_len补齐并返回张量，忽略目标用-100推理与采样（方法级）generate（src/infer.py:32–83）：规范化提示词（去中文空格）（src/infer.py:35–37）前 5 步屏蔽EOS，首步屏蔽PAD/BOS/UNK（src/infer.py:41–50, 68–73）采样：温度、top-k、top-p、重复惩罚、停止词输出清理：剔除开头标点与空白（src/infer.py:26–30, 82–83）可用性策略（总结）乱码防御：HF BPE 设置 ByteLevel 解码器（src/build_tokenizer.py:6–8）目标对齐：忽略len(prefix)-1确保第一个答案 token 参与训练（src/data.py:28–31）空答防御：生成初期屏蔽EOS与无效 token；必要时添加--stop_stringsA/B 验证与权重切换：扩充数据+2000 步训练，固定问题验证通过后才切换默认权重实测与分析（答案可用、与问题相关）环境与数据：在 mac pro 2.6GHz 6c i7（16GB DDR4）上，使用 510 条训练集与 90 条验证集，CPU 训练 2000 步。耗时与结果：总耗时约 19.78 分钟（≈1186.8s），得到“中文可读、与问题相关”的可用回答（固定问题 Q1/Q2 实测通过）。配置要点：n_layer=4, n_head=4, n_embd=256, seq_len=128；HF ByteLevel BPE 分词器（设置 ByteLevel 解码器）；权重共享、RMSNorm、RoPE；AdamW+预热+余弦；梯度累积与裁剪。效率核心原因（技术角度）：小模型与短序列降低注意力计算开销；权重共享减少参数与内存占用；RMSNorm 与 RoPE 计算简洁且稳定。仅 CPU 优化：限制 DataLoader 开销、设线程数；预热+退火提升早期收敛效率；梯度累积在小内存下获得有效大批次。可用性保障：目标对齐只对答案段计算损失；推理阶段首步/初期屏蔽无效与 EOS、提示规范化、输出清理与停止词，避免空答与乱码。参数规模与计算设定：嵌入维度 d=256、层数 L=4、词表大小 V=824（从 tokenizer/tokenizer.json 读取）。总参数（LM Head 与嵌入权重共享）：公式：Total = V*d + L*(12*d^2 + 11*d) + d含义：V*d：词嵌入（每个词一个长度为 d 的向量）每层约 12*d^2 + 11*d：注意力的线性与投影、前馈两层线性与偏置、两处 RMSNorm 权重合计+ d：最终 RMSNorm 权重代入数字：V*d = 824*256 = 210,944d^2 = 256*256 = 65,536每层：12*d^2 + 11*d = 12*65,536 + 11*256 = 786,432 + 2,816 = 789,248所有层：L*(...) = 4*789,248 = 3,156,992总计：210,944 + 3,156,992 + 256 = 3,368,192校验：与代码实际统计一致（params_model=3,368,192）。常见问题与排查乱码输出：确保已运行 src/build_tokenizer.py，且其设置了 ByteLevel 解码器；查看推理是否使用 HF 分词器路径空输出：提升步数（≥1500），并确认推理阶段首步屏蔽与停止词设置是否生效两个不同问题给出同一答案：小数据短训记忆偏移，提升步数并适度扩充问句变体；或在推理时加--stop_strings快速开始（两分钟上手）安装依赖：python -m pip install -r requirements.txt构建分词器：python -m src.build_tokenizer训练（CPU）：python -m src.train推理验证：Q1：python -m src.infer --prompt "什么是注意力机制？" --temperature 0.0 --show_labelQ2：python -m src.infer --prompt "解释蒸馏水与纯水区别？" --temperature 0.0 --show_label
LLM的应用其响应准确性和相关性显的极其重要。检索增强生成（RAG）通过外部知识库增强模型能力，提供更丰富的上下文信息，减轻幻觉和知识不足等问题。然而，仅依赖简单的RAG范式存在局限性，特别是在处理复杂实体关系和多跳问题时，模型往往难以提供准确答案。[...]
🧩 什么是Token？—— 模型的“语言乐高”简单来说，Token就是大模型眼中的“最小语言单位”，就像乐高积木一样，模型用它们拼出整个语言世界！🌍Token可以是：一个英文字母，比如 a一个完整词语，比如 cat 🐱 或 模型一个词的一部分，比如 un + believable甚至是一个标点符号，比如 ? 或换行符 \n模型在处理文本时，会先把句子“切碎”成Token，再把每个Token映射成一个数字ID，比如："This is a cute cat" → [101, 3847, 7292, 372, 471, 1293, 102]（别问我为什么是这些数字，这是模型的“暗号”啦！🔢）🚀 为什么非要Token化？—— 因为模型其实是“数学宅”啊！你可能会问：为什么不直接给模型看文字？ 因为模型本质上是个“数学工具”，它只认识数字，不认识字！🤖Token化的三大理由：语言太灵活：人类语言千变万化，缩写、错拼、方言…对模型来说简直是“天书”。Token化就是把混乱的文本变成整齐的数字序列，让模型好“消化”。拆分更好学：模型通过Token的组合规律学习语言。比如 un + believable，模型知道 un 表示否定，able 常见于形容词，就能举一反三！省资源：共享子词，减少词表大小。比如所有 -ing 结尾的词共享同一个Token，不用每个都存一遍，省钱又省力！💰🛠 Token在大模型里怎么用？—— 三步走：切分→编码→理解Tokenization（切分） 文本 → Token序列，比如加上特殊标记：[CLS] This is a cute cat [SEP]Embedding（嵌入） 每个Token变成一个向量（一堆数字），表示它的“语义特征”，比如："cat" → [0.0384, -0.0374, 0.0183, ...]模型计算 模型看着这些向量，推算出下一个最可能的Token，再转回文字输出给你！🧠➡️🗣️📌 你必须知道的Token冷知识 🧊首Token延迟：生成第一个Token最慢，因为模型要“读懂全文”，后面的Token就快多啦！⚡Token限制：每个模型都有输入输出上限（比如4K、8K、32K），超长内容会被截断哦！计费方式：大多数API按Token数量收费，包括输入和输出。所以聊天时记得“长话短说”更省钱～💸💡 拓展一下：Token化的“小心机”不同的模型有不同的“切词风格”：BERT喜欢用WordPiece（比如 playing → play + ##ing）GPT系列常用Byte Pair Encoding（BPE）中文模型可能按字切，也可能按词切，甚至混合切！所以，同样的句子，在不同模型眼里可能是不同的Token序列！😉🎯 总结一下Token就是模型理解语言的桥梁，把人类的文字变成机器能算的数字，再变回人类能读的文字。它不仅是技术的核心，也直接关系到模型的效果、速度和成本！
Transformer 是一种神经网络架构。Transformer 最初在2017年的论文《Attention is All You Need》中被提出，并迅速成为深度学习模型的首选架构，广泛应用于文本生成、音频生成、图像识别、蛋白质结构预测等多个领域。核心组件:每个基于Transformer的文本生成模型主要由以下三个关键部分组成1.Embedding（嵌入层）2.Transformer Block（Transformer块）Attention MechanismMLP (Multilayer Perceptron) Layer3.Output Probabilities（输出概率）Embedding（嵌入层）​步骤1：Tokenization（分词）:​ 输入文本被分解成更小的单元，称为tokens（可以是单词或子词）。例如，输入"Data visualization empowers users to" 可能会被分解为["Data", "visual", "##ization", "empowers", "users", "to"]。GPT-2 的词汇表包含50,257个唯一的tokens。​步骤2：Token Embedding（token嵌入）:​每个token被映射到一个高维向量空间中，这个向量捕捉了token的语义信息。例如，GPT-2 Small 模型使用768维的向量来表示每个token。这些嵌入向量存储在一个形状为(vocab_size:词汇表大小, hidden_size:隐藏层维度) 的矩阵中。​步骤3：Positional Encoding（位置编码）:​为了捕捉序列中的位置信息，每个token还会附加一个位置编码。位置编码可以是固定的（如正弦/余弦函数）或可训练的（如GPT-2中直接训练的位置编码）。位置编码确保模型能够区分相同token在不同位置的不同含义。​步骤4：Final Embedding（最终嵌入）:​将token嵌入和位置编码相加，得到最终的嵌入表示。这一步使得模型不仅能够理解token的语义，还能理解它们在序列中的相对位置。Transformer Block（Transformer块）Transformer Block是Transformer架构的核心组件，通常由多个相同的块堆叠而成。每个块包括两个主要部分：Multi-Head Self-Attention（多头自注意力机制）MLP（多层感知机）Multi-Head Self-Attention（多头自注意力机制）Self-Attention使模型可以关注输入的相关部分，能够捕获数据中的复杂关系和依赖关系。步骤1：Query, Key, and Value Matrices（QKV矩阵）每个token的嵌入向量通过线性变换转换为三个向量：Query (Q)、Key (K) 和 Value (V)。这些向量用于计算注意力分数，确定每个token与其他token的相关性。Query (Q) ：搜索引擎栏中键入的搜索文本。这是您想要“查找更多信息”的令牌。Key (K) ：搜索结果窗口中每个网页的标题。它代表了查询可以满足的可能标记。Value (V) ：显示的网页的实际内容。将适当的搜索词（Query）与相关结果（Key）匹配，获得最相关页面的内容（Value）。步骤2：Masked Self-Attention（掩码自注意力）在生成任务中，为了防止模型“窥探”未来的信息，会应用掩码。具体来说，上三角矩阵的值被设置为负无穷大，使得模型只能关注当前及之前的token。​Attention Score​：Query和Key矩阵的点积决定了每个查询与每个密钥的对齐，生成一个反映所有输入令牌之间关系的方形矩阵。​Masking：​将屏蔽应用于注意力矩阵的上三角形，以防止模型访问未来令牌，将这些值设置为负无穷大。该模型需要学习如何在不“窥视”未来的情况下预测下一个token。​Softmax：​屏蔽后，注意力得分通过softmax操作转换为概率，该操作取每个注意力分数的指数。矩阵的每一行总和为一，并表示其左侧所有其他令牌的相关性。步骤3：Attention Output（注意力输出）计算注意力分数后，通过softmax函数将其转换为概率分布，然后与Value矩阵相乘，得到最终的注意力输出。GPT-2 使用12个自注意力头，每个头捕捉不同的token间关系。这些头的输出被拼接在一起并通过一个线性投影层。MLP（多层感知机）经过多头自注意力机制处理后的token表示被传递给MLP层，以进一步增强其表达能力。MLP层通常包括两层线性变换，中间夹着一个激活函数（如GELU）。第一层将输入维度扩展四倍，第二层再将其压缩回原始维度。Output Probabilities（输出概率）经过所有Transformer块处理后的输出被传递给最终的线性层，该层将表示投影到词汇表大小的空间中，生成logits。通过softmax函数将logits转换为概率分布，任何令牌都可以是下一个单词，因此这个过程允许我们简单地根据它们成为下一个单词的可能性对这些令牌进行排名。从而预测下一个最有可能出现的token。词汇中的每个令牌都根据模型的输出对数分配一个概率。这些概率决定了每个令牌成为序列中下一个单词的可能性。Transformer组成BERTBERT是一种基于Transformer的预训练语言模型，引入了双向Transformer编码器，这使得模型可以同时考虑输入序列的前后上下文信息。输入层（Embedding）：Token Embeddings：将单词或子词转换为固定维度的向量。Segment Embeddings：用于区分句子对中的不同句子。Position Embeddings：由于Transformer模型本身不具备处理序列顺序的能力，所以需要加入位置嵌入来提供序列中单词的位置信息。编码层（Transformer Encoder）：BERT模型使用双向Transformer编码器进行编码。输出层（Pre-trained Task-specific Layers）：MLM输出层：用于预测被掩码（masked）的单词。在训练阶段，模型会随机遮盖输入序列中的部分单词，并尝试根据上下文预测这些单词。NSP输出层：用于判断两个句子是否为连续的句子对。在训练阶段，模型会接收成对的句子作为输入，并尝试预测第二个句子是否是第一个句子的后续句子。以下是bert-base-chinese模型信息：# 加载预训练模型 import torch from transformers import BertModel DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") pretrained = BertModel.from_pretrained("/Volumes/Date/huggingface/model/bert-base-chinese/models--bert-base-chinese/snapshots/c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f").to(DEVICE) print(pretrained) """ BertModel( (embeddings): BertEmbeddings( # 编码层（词向量化）：文本位置编码编码为词向量 (word_embeddings): Embedding(21128, 768, padding_idx=0) (position_embeddings): Embedding(512, 768) (token_type_embeddings): Embedding(2, 768) (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True) (dropout): Dropout(p=0.1, inplace=False) ) (encoder): BertEncoder( # 特征提取 (layer): ModuleList( (0-11): 12 x BertLayer( # 12层 (attention): BertAttention( (self): BertSdpaSelfAttention( (query): Linear(in_features=768, out_features=768, bias=True) (key): Linear(in_features=768, out_features=768, bias=True) (value): Linear(in_features=768, out_features=768, bias=True) (dropout): Dropout(p=0.1, inplace=False) ) (output): BertSelfOutput( (dense): Linear(in_features=768, out_features=768, bias=True) (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True) (dropout): Dropout(p=0.1, inplace=False) ) ) (intermediate): BertIntermediate( (dense): Linear(in_features=768, out_features=3072, bias=True) (intermediate_act_fn): GELUActivation() ) (output): BertOutput( (dense): Linear(in_features=3072, out_features=768, bias=True) (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True) (dropout): Dropout(p=0.1, inplace=False) ) ) ) ) (pooler): BertPooler( # 输出层 (dense): Linear(in_features=768, out_features=768, bias=True) #输出728特征 (activation): Tanh() ) ) """Embeddings 层（词向量化）Word Embeddings: 将输入文本中的每个单词映射为一个固定维度的向量（例如768维）。这是通过查找预训练的嵌入矩阵来实现的。Position Embeddings: 由于BERT是双向的，它需要位置信息来理解句子中单词的顺序。位置嵌入为每个单词添加了其在句子中的位置信息。Token Type Embeddings: 用于区分不同句子（例如在句子对任务中），以便模型知道哪些标记属于哪个句子。LayerNorm: 对嵌入进行归一化处理，以确保数值稳定。Dropout: 随机丢弃一部分神经元，防止过拟合。Encoder 层（特征提取）BertEncoder: 包含多个 BertLayer，每个 BertLayer 又包含两个子模块：\`Attention\` 和 Feed-Forward Network。Attention:Self-Attention: 计算输入序列中每个单词与其他单词之间的关系。这使得模型可以关注到上下文中的相关信息。Output: 对自注意力的结果进行线性变换，并应用归一化和dropout。Intermediate:Linear: 扩展维度（例如从768维扩展到3072维），并应用激活函数（如GELU）。Output:Linear: 缩小维度（例如从3072维缩小回768维），并应用归一化和dropout。Pooler 层（输出层）​BertPooler​: 用于生成一个固定长度的向量表示整个输入序列。通常取 [CLS] 标记对应的隐藏状态，并通过线性变换和激活函数（如Tanh）得到最终表示。GPTGPT也是一种基于Transformer的预训练语言模型，使用了单向Transformer编码器，这使得模型可以更好地捕捉输入序列的上下文信息。 输入层（Input Embedding）：将输入的单词或符号转换为固定维度的向量表示。可以包括词嵌入、位置嵌入等，以提供单词的语义信息和位置信息。编码层（Transformer Encoder）：GPT模型使用单向Transformer编码器进行编码和生成。输出层（Output Linear and Softmax）：线性输出层将最后一个Transformer Decoder Block的输出转换为词汇表大小的向量。Softmax函数将输出向量转换为概率分布，以便进行词汇选择或生成下一个单词。以下是GPT-2模型信息：from transformers import BertTokenizer,GPT2LMHeadModel,TextGenerationPipeline tokenizer = BertTokenizer.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3") model = GPT2LMHeadModel.from_pretrained(r"/Volumes/Date/huggingface/model/gpt2-chinese/models--uer--gpt2-chinese-cluecorpussmall/snapshots/c2c0249d8a2731f269414cc3b22dff021f8e07a3") print(model) “”“ GPT2LMHeadModel( (transformer): GPT2Model( (wte): Embedding(21128, 768) (wpe): Embedding(1024, 768) (drop): Dropout(p=0.1, inplace=False) (h): ModuleList( (0-11): 12 x GPT2Block( (ln_1): LayerNorm((768,), eps=1e-05, elementwise_affine=True) (attn): GPT2SdpaAttention( (c_attn): Conv1D(nf=2304, nx=768) (c_proj): Conv1D(nf=768, nx=768) (attn_dropout): Dropout(p=0.1, inplace=False) (resid_dropout): Dropout(p=0.1, inplace=False) ) (ln_2): LayerNorm((768,), eps=1e-05, elementwise_affine=True) (mlp): GPT2MLP( (c_fc): Conv1D(nf=3072, nx=768) (c_proj): Conv1D(nf=768, nx=3072) (act): NewGELUActivation() (dropout): Dropout(p=0.1, inplace=False) ) ) ) (ln_f): LayerNorm((768,), eps=1e-05, elementwise_affine=True) ) (lm_head): Linear(in_features=768, out_features=21128, bias=False) ) ”“”模型输入数据信息​输入文本​：输入文本需要先通过分词器（如 BertTokenizer）进行编码，转换为模型可以理解的格式。具体来说，输入文本会被分割成一个个token（词汇或字符），并映射到模型的词汇表中对应的ID。输入张量​input\_ids​：这是一个二维张量，形状为 [batch_size, sequence_length]，其中 batch_size 是批次大小，\`sequence\_length\` 是序列长度。每个元素是词汇表中的token ID。​attention\_mask​（可选）：用于指示哪些位置是有效的token（值为1），哪些位置是填充的（值为0）。形状为 [batch_size, sequence_length]。​position\_ids​（可选）：用于指示每个token在序列中的位置。形状为 [batch_size, sequence_length]。​token\_type\_ids​（可选）：用于区分不同类型的token（例如，在句子对任务中区分两个句子）。形状为 [batch_size, sequence_length]。模型输出数据信息输出张量​logits​：这是模型生成的每个位置上所有可能token的概率分布。形状为 [batch_size, sequence_length, vocab_size]，其中 vocab_size 是词汇表的大小（21128）。每个位置上的概率分布可以通过softmax函数转换为概率值。​past\_key\_values​（可选）：用于加速推理过程中的自回归生成。包含之前计算的注意力键和值，可以在生成下一个token时复用。模型结构Embedding层​wte (word embeddings)​：将输入的token ID嵌入到768维的向量空间中。形状为 [vocab_size, hidden_size]，其中 hidden_size=768。​wpe (position embeddings)​：将每个token的位置信息嵌入到768维的向量空间中。形状为[max_position_embeddings, hidden_size]，其中** max_position_embeddings=1024。​Dropout层：​在嵌入层之后应用一个dropout层，以防止过拟合。dropout概率为0.1。​Transformer层：​包含12个GPT2Block，每个块由以下部分组成：​LayerNorm (ln\_1)​：在多头自注意力机制之前应用层归一化。​Attention (attn)​：多头自注意力机制，用于捕捉输入序列中的依赖关系。包括三个子模块：​c\_attn​：线性变换，将输入映射到查询、键和值的组合空间。​c\_proj​：线性变换，将注意力结果映射回隐藏状态空间。attn\_dropout 和​resid\_dropout​：分别应用于注意力权重和残差连接的dropout层。​LayerNorm (ln\_2)​：在前馈神经网络之前应用层归一化。​MLP (mlp)​：两层全连接网络，激活函数为NewGELUActivation，并在最后一层应用dropout。​Final LayerNorm：​在所有Transformer层之后应用最终的层归一化。​Language Model Head (lm\_head)：​线性变换，将隐藏状态映射回词汇表大小的空间。形状为[hidden_size, vocab_size]，没有偏置项。工作流程1.输入处理​：输入文本通过分词器编码为input_ids，并可能附加attention_mask 和position_ids。2.嵌入层​：将input_ids 和position_ids 转换为嵌入向量，并应用dropout。3.Transformer层​：嵌入向量依次通过12个GPT2Block，每个块内部进行多头自注意力计算和前馈神经网络变换。4.输出层​：最终的隐藏状态通过lm_head 线性变换，得到每个位置上所有可能token的概率分布。5.生成文本​：使用生成策略（如贪心搜索、束搜索或采样）从概率分布中选择最合适的token，逐步生成新的文本。
在数学中，向量（也称为欧几里得向量、几何向量），指具有大小（magnitude）和方向的量。二维平面中，一个向量表示xy坐标轴的坐标点 A(1，2)，在编程领域，一个二维向量对应的就是一个大小为二的float类型的数组。[...]