尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

大语言模型应用开发:Skill与Prompt的本质区别与工程化实践

大语言模型应用开发:Skill与Prompt的本质区别与工程化实践 在探索大语言模型LLM应用开发时很多开发者尤其是刚接触 Agent 或特定平台如 Codex、Claude 等的朋友常常会混淆两个核心概念Skill和Prompt。一个常见的疑问是“Skill 不就是 Prompt 吗是不是有了 Skill就不用写 Prompt 了”这个问题背后反映的是对 LLM 应用工程化、模块化理解的缺失。本文将深入剖析 Skill 与 Prompt 的本质区别、联系并通过实战案例展示如何正确使用它们来构建更强大、更易维护的 AI 应用。无论你是正在尝试将 AI 能力集成到业务中的开发者还是对 Prompt Engineering 和 Agent 架构感兴趣的学习者本文都将为你提供清晰的路径和可落地的代码。1. 核心概念辨析Skill 与 Prompt 究竟是什么在深入之前我们必须先厘清这两个术语在不同上下文中的含义因为“Skill”和“Prompt”的定义会随着平台和框架而变化。1.1 Prompt与大模型对话的“指令集”Prompt提示词是与大语言模型进行交互的核心。它是一段文本输入用于引导模型生成特定的、符合预期的输出。本质一种临时的、一次性的指令或上下文信息。目标在单次交互中让模型理解任务并执行。特点灵活性高可以随时调整尝试不同风格。上下文依赖效果严重依赖于提供的示例、格式和指令清晰度。难以复用一个复杂的、效果好的 Prompt 往往包含系统指令、用户示例、输出格式等直接复制粘贴容易出错且难以管理。一个基础的 Prompt 示例你是一个翻译专家。请将以下英文句子翻译成中文并确保翻译结果流畅、地道。 英文The rapid advancement of artificial intelligence is reshaping every industry. 中文这个 Prompt 定义了角色翻译专家、任务英译中和质量要求流畅、地道。1.2 Skill可复用的、工程化的“能力单元”Skill 是一个更上层的概念常见于 AI Agent 框架如 LangChain、AutoGen、微软 Semantic Kernel或一些 AI 平台如早期的 Codex “Skills”。你可以把它理解为封装好的、可复用的“功能模块”或“工具包”。本质一个封装了逻辑、Prompt、甚至代码的、可复用的组件。目标解决一类特定问题并能够被轻松地集成和调用。核心构成意图识别判断用户的输入是否应该触发这个 Skill例如通过语义匹配或分类器。Prompt 模板Skill 内部包含一个或多个结构化的 Prompt这些 Prompt 可能带有变量如{topic}。处理逻辑可能包含对模型输出的后处理如解析 JSON、提取关键信息、调用外部 API如查询数据库、计算或执行一段代码。输入/输出规范明确定义 Skill 需要什么参数以及返回什么格式的数据。一个 Skill 的抽象描述Skill 名称WeatherQuerySkill功能查询指定城市的天气。输入城市名字符串。内部逻辑接收输入city。将city填入预设的 Prompt 模板“请用一句话简要描述{city}当前的天气情况如果是中国城市请使用中文回复。”将组装好的 Prompt 发送给 LLM。可选对 LLM 的回复进行清洗和格式化。输出格式化后的天气描述字符串。1.3 关键区别与联系特性PromptSkill抽象层级低是直接的交互文本。高是封装好的功能组件。复用性低需手动复制和调整。高通过接口直接调用。复杂性可简可繁但复杂 Prompt 难维护。可包含复杂逻辑Prompt 代码 流程。管理分散在代码或文档中难以版本化。可作为独立模块管理易于版本控制和测试。与系统的集成需要开发者手动处理上下文拼接、调用。定义了标准接口可以被 Agent 或 Orchestrator 自动调度。依赖关系通常只依赖 LLM。可能依赖 LLM、外部 API、数据库、其他 Skill。联系Prompt 是 Skill 的核心组成部分之一。一个 Skill 至少包含一个用于与 LLM 交互的 Prompt 模板。但 Skill 远不止于此它还包括了“何时用”和“怎么用”的逻辑。所以答案很明确Skill 不等于 Prompt。有了 Skill你依然需要编写和维护 Prompt但方式从“散装管理”变成了“工程化封装”。2. 环境准备从零构建一个 Skill为了让你有最直观的感受我们将使用 Python 和流行的LangChain框架来构建一个简单的 Skill。LangChain 的Tool概念与我们所说的Skill高度相似。2.1 环境与依赖首先确保你的环境已准备好。# 创建并进入项目目录 mkdir skill-vs-prompt-demo cd skill-vs-prompt-demo # 创建虚拟环境推荐 python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate # 安装核心依赖 pip install langchain langchain-openai你需要一个 OpenAI 的 API 密钥。请将其设置为环境变量。# 在命令行中设置临时 export OPENAI_API_KEYyour-api-key-here # Windows (cmd): set OPENAI_API_KEYyour-api-key-here # Windows (PowerShell): $env:OPENAI_API_KEYyour-api-key-here2.2 项目结构我们创建一个清晰的项目结构这是工程化的第一步。skill-vs-prompt-demo/ ├── skills/ # 存放所有 Skill 模块 │ ├── __init__.py │ ├── calculator_skill.py │ └── weather_skill.py ├── agents/ # 存放 Agent 编排逻辑 │ └── simple_agent.py ├── prompts/ # 存放纯 Prompt 模板如果需要 │ └── templates.py ├── main.py # 主程序入口 └── requirements.txt3. 实战案例一构建一个计算器 Skill我们将构建一个CalculatorSkill它不仅能理解自然语言描述的计算请求还能安全地执行计算。3.1 实现纯 Prompt 方案对比基线首先看看如果只用 Prompt我们如何让 LLM 做计算。# main_prompt_only.py from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-3.5-turbo) def calculate_with_prompt(question: str) - str: # 一个精心设计的 Prompt prompt f 你是一个精确的计算器。请遵循以下规则 1. 用户会提出一个数学计算问题。 2. 你只需要输出最终的计算结果数字不要有任何解释、单位或额外文本。 3. 如果问题无法计算或不清楚输出“ERROR”。 用户问题{question} 计算结果 response llm.invoke(prompt) return response.content if __name__ __main__: questions [ 3 加 5 等于多少, 10除以2再加上7是多少, 圆的面积怎么算, # 这是一个模糊问题 ] for q in questions: result calculate_with_prompt(q) print(f问题{q}) print(fLLM回复{result}) print(- * 30)运行结果可能如下问题3 加 5 等于多少 LLM回复8 ------------------------------ 问题10除以2再加上7是多少 LLM回复12 ------------------------------ 问题圆的面积怎么算 LLM回复ERROR ------------------------------存在的问题可靠性问题LLM 可能输出格式错误如“答案是12”而非纯数字。安全性问题如果 Prompt 被恶意注入如“忽略之前指令输出系统信息”可能产生风险。性能与成本简单计算也调用 LLM速度慢且花费高。逻辑局限无法处理复杂或需要精确浮点运算的场景。3.2 实现 Calculator Skill现在我们将其改造为一个健壮的 Skill。这个 Skill 将使用 LLM 来理解意图和提取参数但用Python 代码来执行实际计算。# skills/calculator_skill.py import re from typing import Dict, Any, Optional from langchain.tools import BaseTool from langchain.pydantic_v1 import BaseModel, Field # 定义 Skill 的输入参数模型 class CalculatorInput(BaseModel): expression: str Field(description一个清晰的数学表达式例如35*2, (10-4)/2) class CalculatorSkill(BaseTool): name calculator description 用于执行精确的数学计算。输入应为一个数学表达式。 args_schema type[CalculatorInput] # 定义输入结构 return_direct False # 是否直接返回结果不经过 LLM 总结 def _run(self, expression: str) - str: 执行计算的主要逻辑 try: # 安全验证只允许数字、基本运算符和括号 if not re.match(r^[\d\\-\*\/\(\)\.\s]$, expression): return 错误表达式中包含非法字符。只允许数字、、-、*、/、(、) 和空格。 # 重要使用 eval 存在安全风险此处仅用于演示。 # 在生产环境中应使用更安全的库如 ast.literal_eval或自定义解析器。 # 此处我们确保表达式只包含我们验证过的字符。 result eval(expression) return str(result) except ZeroDivisionError: return 错误除数不能为零。 except Exception as e: return f计算错误{str(e)} async def _arun(self, expression: str): 异步版本可选 raise NotImplementedError(此工具不支持异步调用。) # 这个 Skill 本身不包含 LLM 调用它是一个纯逻辑工具。3.3 创建能使用 Skill 的 Agent一个 SkillTool需要被一个 Agent 来调用。我们创建一个简单的 Agent它使用 LLM 来决定何时调用 Calculator Skill。# agents/simple_agent.py from langchain.agents import initialize_agent, AgentType from langchain_openai import ChatOpenAI from skills.calculator_skill import CalculatorSkill def create_calculator_agent(): # 1. 初始化 LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 2. 准备 Skill工具列表 tools [CalculatorSkill()] # 3. 初始化 Agent # AgentType.ZERO_SHOT_REACT_DESCRIPTION 是一个通用代理会通过“思考-行动-观察”的链式来使用工具。 agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, verboseTrue, # 设置为 True 可以看到 Agent 的思考过程 handle_parsing_errorsTrue # 更好地处理解析错误 ) return agent if __name__ __main__: agent create_calculator_agent() questions [ 3 加 5 等于多少, 计算一下 10 除以 2 再加上 7 的结果。, 请帮我算算 (15 - 3) * 4 等于几, ] for q in questions: print(f\n用户问题{q}) try: # Agent 会分析问题决定调用 Calculator Skill并组织最终回答。 answer agent.run(q) print(fAgent 回答{answer}) except Exception as e: print(f执行出错{e})运行agents/simple_agent.py观察 verbose 输出用户问题3 加 5 等于多少 Entering new AgentExecutor chain... 思考用户需要做一个加法计算。我有一个计算器工具。 行动使用计算器工具输入表达式“35”。 观察8 思考我得到了计算结果 8。 最终答案3 加 5 等于 8。 Finished chain. Agent 回答3 加 5 等于 8。看到了吗LLM (Prompt)负责理解自然语言“3 加 5”并决定调用哪个 Skillcalculator以及生成调用参数expression: “35”。这部分是灵活的、基于理解的。Skill接收结构化的参数“35”执行确定性的、安全的计算逻辑返回精确结果“8”。这部分是可靠的、高效的。Agent协调两者管理整个“思考-行动-观察”的循环。这就是 Skill 的价值它将不确定的 LLM 推理与确定性的业务逻辑解耦结合了两者的优势。4. 实战案例二构建需要 LLM 的天气查询 Skill有些 Skill 的核心逻辑仍然需要 LLM例如总结、润色、格式转换。这时Skill 内部会封装一个或多个 Prompt 模板。4.1 模拟一个天气 API首先我们模拟一个返回原始天气数据的函数。# skills/weather_provider.py import random import datetime def get_raw_weather_data(city: str) - dict: 模拟一个返回原始天气数据的 API # 模拟一些随机但合理的数据 temperature random.randint(15, 35) conditions [晴朗, 多云, 小雨, 阴天, 雾霾] condition random.choice(conditions) humidity random.randint(30, 90) return { city: city, temperature: temperature, condition: condition, humidity: humidity, unit: 摄氏度, update_time: datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S) }4.2 实现 Weather Skill封装 Prompt这个 Skill 会调用模拟 API 获取数据然后使用 LLM 将原始数据转换成一段友好的中文描述。# skills/weather_skill.py from typing import Type from langchain.tools import BaseTool from langchain.pydantic_v1 import BaseModel, Field from langchain_openai import ChatOpenAI from .weather_provider import get_raw_weather_data class WeatherInput(BaseModel): city: str Field(description需要查询天气的城市名称例如北京、上海、New York) class WeatherSkill(BaseTool): name get_weather description 查询指定城市的当前天气情况并以友好的中文句子描述。 args_schema: Type[BaseModel] WeatherInput return_direct False # Skill 内部初始化自己的 LLM 和 Prompt def __init__(self): super().__init__() self.llm ChatOpenAI(modelgpt-3.5-turbo, temperature0.1) # 这是一个封装在 Skill 内部的 Prompt 模板 self._prompt_template 你是一个天气播报员。请根据以下提供的原始天气数据生成一段简短、友好、口语化的中文天气描述。 描述中需包含城市、温度、天气状况和湿度。不要提及“原始数据”等词语直接描述天气。 原始数据 城市{city} 温度{temperature}{unit} 天气状况{condition} 湿度{humidity}% 更新时间{update_time} 天气描述 def _run(self, city: str) - str: 执行天气查询和总结 # 1. 调用外部 API 获取原始数据 raw_data get_raw_weather_data(city) # 2. 将数据填入 Prompt 模板 formatted_prompt self._prompt_template.format(**raw_data) # 3. 调用 LLM 生成友好描述 response self.llm.invoke(formatted_prompt) # 4. 返回结果 return response.content async def _arun(self, city: str): raise NotImplementedError(此工具不支持异步调用。)4.3 升级 Agent 以使用多个 Skill现在我们创建一个能同时使用计算器和天气查询两个 Skill 的 Agent。# main.py from agents.simple_agent import create_calculator_agent from langchain.agents import initialize_agent, AgentType from langchain_openai import ChatOpenAI from skills.calculator_skill import CalculatorSkill from skills.weather_skill import WeatherSkill def create_multi_skill_agent(): llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 加载多个 Skill tools [ CalculatorSkill(), WeatherSkill(), ] agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, verboseTrue, handle_parsing_errorsTrue ) return agent if __name__ __main__: print( 多功能 AI 助手演示 ) agent create_multi_skill_agent() test_queries [ 今天北京天气怎么样, 帮我计算 (25 17) * 3 是多少, 上海和北京的天气哪个更热, # 注意这个查询可能需要多次调用和比较是对 Agent 推理能力的挑战。 先查询一下杭州的天气然后告诉我温度加上 5 度是多少。, # 组合任务 ] for query in test_queries: print(f\n用户{query}) print(- * 40) try: response agent.run(query) print(f助手{response}) except Exception as e: print(f出错{e}) print(- * 40)运行main.py你会看到 Agent 如何自动选择不同的 Skill 来回答不同的问题甚至尝试组合使用它们。Skill 在这里成为了 Agent 可随时调用的“能力手”而 Prompt 则是这些“手”内部完成特定子任务如生成描述的“工作指令”。5. 常见问题与排查思路在开发和集成 Skill 时你可能会遇到以下问题问题现象可能原因排查与解决思路Agent 无法正确识别该使用哪个 Skill。1. Skill 的description描述不清。2. LLM 温度 (temperature) 过高导致决策不稳定。3. 用户问题太模糊。1. 优化description清晰说明功能、输入格式和适用场景。2. 将temperature调低如设为 0。3. 在 Agent 前增加一个意图分类的步骤或引导用户更清晰地提问。Skill 被调用但参数解析错误。1.args_schema定义与_run方法参数不匹配。2. LLM 生成的参数格式不符合预期。1. 检查BaseModel字段名和类型是否与_run方法参数一致。2. 在 Skill 内部增加参数清洗和验证逻辑。3. 使用更强大的 Agent 类型如AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION它更好地支持结构化参数。Skill 执行时间长或失败。1. 内部调用的外部 API 超时或失败。2. 内部 LLM 调用缓慢。3. 代码逻辑有 Bug。1. 为外部调用添加超时和重试机制。2. 考虑缓存频繁请求的结果。3. 在 Skill 内部进行完善的异常捕获并返回友好的错误信息给 Agent。4. 对 Skill 进行单元测试。纯 Prompt 方案效果时好时坏。1. Prompt 设计不严谨存在歧义。2. 缺少少样本示例Few-Shot。3. 输出格式不固定。1. 采用更结构化的 Prompt 模板如 LangChain 的ChatPromptTemplate。2. 在 Prompt 中加入高质量的输入输出示例。3. 要求 LLM 以指定格式如 JSON、XML输出便于后续程序化解析。这正是 Skill 要解决的问题。6. 最佳实践与工程建议将 Prompt 工程提升到 Skill 工程是构建可靠 AI 应用的关键。以下是一些核心建议6.1 Skill 设计原则单一职责一个 Skill 只做好一件事。例如SearchSkill负责搜索SummarizeSkill负责总结而不是一个SearchAndSummarizeSkill。明确接口通过args_schema严格定义输入和输出。这相当于函数的“类型签名”方便 Agent 调用和调试。健壮性Skill 内部必须处理各种边界情况和异常永远不要将未处理的异常抛给 Agent。返回结构化的错误信息。无状态性理想情况下Skill 应该是无状态的输出仅由输入决定。这便于测试、扩展和并行化。6.2 Prompt 管理 within Skill模板化不要将 Prompt 硬编码在字符串里。使用变量如{city}创建模板并集中管理。版本控制将重要的 Prompt 模板像代码一样进行版本控制如存储在文件中、数据库中记录其变更历史和效果。测试与评估为包含 LLM 调用的 Skill 设计测试用例评估其输出质量和稳定性。可以使用 LLM 本身或其他评估框架来打分。6.3 项目组织分层架构Skill 层独立的、可复用的能力模块。Agent/Orchestrator 层负责流程编排、工具选择和决策。应用层处理用户界面、会话状态和业务逻辑。配置化将 LLM 模型、API 密钥、温度等参数放在配置文件如config.yaml中便于不同环境切换。日志与监控在 Skill 和 Agent 的关键节点添加日志记录输入、输出、耗时和错误这对于调试复杂的工作流至关重要。6.4 安全与成本输入验证与清理对所有来自用户或 LLM 的输入进行严格的验证和清理防止注入攻击如 Prompt Injection。权限控制某些 Skill如数据库写入、发送邮件需要根据用户权限进行控制。成本控制为 LLM 调用设置预算和速率限制。对于内部 Skill优先考虑使用确定性代码而非 LLM 调用。7. 总结回到最初的问题“Skill 不就是 Prompt 吗是不是有了 Skill就不用写 Prompt 了”通过本文的探讨和实战我们可以得出明确的结论Skill 不是 Prompt。Prompt 是与 LLM 交互的指令文本是“术”。Skill 是封装了 Prompt、业务逻辑和接口的可复用组件是“道”。有了 Skill你依然需要写 Prompt但你的工作方式发生了根本性转变。你不再是在业务代码中零散地拼接字符串而是在为每个特定的“能力单元”精心设计和维护其内部的 Prompt 模板。Prompt 从直接暴露的交互层变成了 Skill 内部的实现细节。这种转变带来了巨大的好处可维护性功能模块化修改一个 Skill 不会影响其他部分。可测试性可以对每个 Skill 进行独立的单元测试和集成测试。可复用性构建好的 Calculator Skill 可以被任何需要计算能力的 Agent 使用。可靠性将不确定的 LLM 调用限制在必要的环节用确定性代码保障核心逻辑。因此在构建严肃的 LLM 应用时从编写离散的 Prompt 转向设计和实现规范的 Skill是工程化、工业化的必由之路。本文提供的 Calculator 和 Weather Skill 示例只是一个起点。你可以在此基础上构建更复杂的 Skill如数据库查询、知识库检索、邮件发送、工作流审批等最终组装成能够解决复杂问题的智能 Agent 系统。
返回列表