4.prompt

📅 2026/7/6 15:05:41
4.prompt
Prompt engineering提示词工程用好prompt可以减轻预处理和后处理的工作量和复杂度1.Prompt调优1.如果知道训练数据可以根据训练数据参考训练数据来构造prompt2.不知道训练数据根据已知的例如openai对markdown格式友好对xml友好未知的只能不断尝试高质量prompt核心具体、丰富、少歧义若底层大模型替换了prompt需要进行重新调优)2.Prompt构成角色给ai定义一个任务角色指示对任务进行描述上下文给出与任务相关的其他背景信息例子提供可能的输入示例以及模型期望的输出输入任务的输入信息输出输出格式描述大模型对prompt开头和结尾的内容更敏感先定义角色把问题域收窄实战项目例智能客服根据用户的咨询推荐产品流量包思路语音识别语音转为文字-语义理解NLU:做出行为例如进行排序-DST由DST生成的结果去到数据库中进行查询-决策:查询得到值后返回-自然语言生成-输出给用户NLU-DST:把输入的自然语言转成结构化的表示DST-Policy从结构化的表示生成策略用prompt实现DST不是唯一的选择有点节省开发量缺点调优相对复杂最好用动态例子也可以用prompt实现NLU用传统方法维护DST优点DST环节可控性更高缺点需要结合业务know-how设计状态更新机制解冲突实现前置导入依赖、加载环境变量、初始化openai、调用大模型#导入依赖库 from openai import OpenAI from dotenv import load_dotenv,find_dotenv #加载.env文件中定义的环境变量 _load_dotenv(find_dotenv()) #初始化OpenAI客户端 clientOpenAI()#默认使用环境变量中的apikey #基于prompt生成文本 def get_completion(prompt,modelgpt-3.5-turbo): messages[{role:user,content:prompt}] responseclent.chat.completion.create( modelmodel, messagesmessages, temperature0 ) return response.choices[0].message.contentdemo1简单prompt从用户的一句话里自动提取出他想要的流量套餐条件并输出成程序能直接用的 JSON 结果。#任务描述 instruction 你的任务是识别用户对手机流量套餐产品的选择条件。 每种流量套餐产品包含三个属性名称月费价格月流量。 根据用户输入识别用户在上述三种属性上的倾向。 #输出格式 output_format 以json格式输出 #用户输入 input_text 办个100G的套餐 #prompt模板instruction和input_text会被替换为上面的内容 promptf {instruction} {output_format} 用户输入 {input_text} #调用大模型 responseget_completion(prompt) print(response)目的以及作用把口语化需求转为规范数据方便系统处理业务demo2精准描述把用户说的口语化套餐需求精准转换成后端系统能直接使用的、严格结构化的查询条件。#把输出格式定义的更精细 #任务描述增加了字段的英文标识符 instruction 你的任务是识别用户对手机流量套餐产品的选择条件。 每种流量套餐产品包含三个属性名称name月费价格price月流量data。 根据用户输入识别用户在上述三种属性上的倾向。 output_format 以json格式输出。 1.name字段取值为string类型取值必须为以下之一经济套餐、畅游套餐、无限套餐 2.price字段的取值为一个结构体或null包含两个字段 1operatorstring类型取值范围‘’小于等于大于等于 2valueint类型 3.data字段的取值取值为一个结构体或null包含两个字段 1operatorstring类型取值范围‘’小于等于大于等于 2valueint类型或stringstring类型只能是‘无上限’ 4.用户对意图可以包含按price或data排序以sort字段标识取值为一个结构体 1结构体中以“ordering“”descend”表示按升序排序以“value”字段存储待排序的字段 2结构体中以“ordering“”ascend”表示按升序排序以“value”字段存储待排序的字段 只输出中只包含用户提及的字段不要猜测用户未直接提及的任意字段不输出值为null的字段 input_text 办个100G以上的套餐 promptf {instruction} {output_format} 用户输入 {input_text} #调用大模型 responseget_completion(prompt) print(response)demo3加入例子通过提供例子来展示希望达到的输出效果#加入例子 examples 便宜的套餐{sort:{orderingascend,valueprice}} 有没有不限流量的:{data:{operator:,value:无上限}} 流量大的:{sort:{orderingdescend,valuedata}} 100G以上流量的套餐最便宜的是哪个:{sort:{orderingascend,valueprice},data:} 月费不超过200的:{price:{operator:,value:200}} 就要月费180那个套餐:{price:{operator:,value:180}} 经济套餐:{name:经济套餐} input_text有没有便宜的套餐 promptf {instruction} {output_format} 例如 {examples} 用户输入 {input_text} responseget_completion(prompt) print(response)demo4多轮对话#把输出格式定义的更精细 #任务描述增加了字段的英文标识符 instruction 你的任务是识别用户对手机流量套餐产品的选择条件。 每种流量套餐产品包含三个属性名称name月费价格price月流量data。 根据用户输入识别用户在上述三种属性上的倾向。 output_format 以json格式输出。 1.name字段取值为string类型取值必须为以下之一经济套餐、畅游套餐、无限套餐 2.price字段的取值为一个结构体或null包含两个字段 1operatorstring类型取值范围‘’小于等于大于等于 2valueint类型 3.data字段的取值取值为一个结构体或null包含两个字段 1operatorstring类型取值范围‘’小于等于大于等于 2valueint类型或stringstring类型只能是‘无上限’ 4.用户对意图可以包含按price或data排序以sort字段标识取值为一个结构体 1结构体中以“ordering“”descend”表示按升序排序以“value”字段存储待排序的字段 2结构体中以“ordering“”ascend”表示按升序排序以“value”字段存储待排序的字段 只输出中只包含用户提及的字段不要猜测用户未直接提及的任意字段不输出值为null的字段 examples 客服有什么可以帮您 用户100G套餐有什么 {data:{operator:,value:100}} 客服有什么可以帮您 用户100G套餐有什么 客服我们现在有无限套餐不限流量月费300元 用户太贵了有200元以内的吗 {data:{operator:,value:100},price:{operator:,value:200}}} 客服有什么可以帮您 用户便宜的套餐有什么 客户我们现在有经济套餐每月50元10G流量 用户100G以上的有什么 {data:{operator:,value:100},sort:{ordering:ascend,value:price}}} 客服有什么可以帮您 用户100G套餐有什么 客服我们现在有畅游套餐流量100G月费180元 用户流量最多的呢 {sort:{ordering:descend,value:data},data:{operator:,value:100}} input_text 哪个便宜 #多轮对话上下文 contextf 客服有什么可以帮您 用户有什么100G以上的套餐推荐 客服我们有畅游和无限套餐您有什么价格倾向呢 用户{input_text} promptf {instruction} {output_format} {examples} 用户输入 {input_text} #调用大模型 responseget_completion(prompt) print(response)demo5客服机器人#实现对话策略和NLG import json import copy from openai import OpenAI from dotenv import load_dotenv,find_dotenv _load_dotenv(find_dotenv()) clientOpenAI() instruction 你的任务是识别用户对手机流量套餐产品的选择条件。 每种流量套餐产品包含三个属性名称name月费价格price月流量data。 根据用户输入识别用户在上述三种属性上的倾向。 #输出格式 output_format 以json格式输出。 1.name字段取值为string类型取值必须为以下之一经济套餐、畅游套餐、无限套餐 2.price字段的取值为一个结构体或null包含两个字段 1operatorstring类型取值范围‘’小于等于大于等于 2valueint类型 3.data字段的取值取值为一个结构体或null包含两个字段 1operatorstring类型取值范围‘’小于等于大于等于 2valueint类型或stringstring类型只能是‘无上限’ 4.用户对意图可以包含按price或data排序以sort字段标识取值为一个结构体 1结构体中以“ordering“”descend”表示按升序排序以“value”字段存储待排序的字段 2结构体中以“ordering“”ascend”表示按升序排序以“value”字段存储待排序的字段 只输出中只包含用户提及的字段不要猜测用户未直接提及的任意字段不输出值为null的字段 class NLU: def __init__(self): self.prompt_templatef{instruction}\n\n{output_format}\n\n{examples}\n def _get_completion(self,prompt,moddelgpt-3.5-turbo): messages [{role: user, content: prompt}] response client.chat.completions.create( modelmodel, messagesmessages, temperature0, # 模型输出的随机性0 表示随机性最小 ) semantics json.loads(response.choices[0].message.content) # 过滤掉值为空的键只保留有内容的字段 return {k: v for k, v in semantics.items() if v} def parse(self, user_input): # 把模板里的占位符替换成用户输入 prompt self.prompt_template.replace(__INPUT__, user_input) return self._get_completion(prompt) class DST: def __init__(self): pass def update(self, state, nlu_semantics): # 如果用户语义里包含name清空历史对话状态 if name in nlu_semantics: state.clear() # 处理sort排序相关的槽位逻辑 if sort in nlu_semantics: # 从NLU结果中取出排序字段和值 slot nlu_semantics[sort][value] # 如果当前状态中已有该槽位且操作符是则删除该槽位 if slot in state and state[slot][operator] : del state[slot] # 将NLU解析出的所有新语义信息更新到对话状态中 for k, v in nlu_semantics.items(): state[k] v # 返回更新后的对话状态 return state # 模拟数据库类负责根据对话状态筛选、排序套餐数据 class MockedDB: def __init__(self): # 模拟的手机流量套餐数据 self.data [ {name: 经济套餐, price: 50, data: 10, requirement: None}, {name: 畅游套餐, price: 100, data: 100, requirement: None}, {name: 无限套餐, price: 300, data: 1000, requirement: None}, {name: 校园套餐, price: 150, data: 200, requirement: 在校生}, ] def retrieve(self, **kwargs): records [] # 遍历所有套餐数据按条件筛选 for r in self.data: select True # 处理特殊用户身份限制如校园套餐的在校生要求 if r[requirement]: # 如果用户状态里没有status或身份不匹配则跳过该套餐 if status not in kwargs or kwargs[status] ! r[requirement]: continue # 遍历所有筛选条件排除排序字段 for k, v in kwargs.items(): # 排序字段不参与筛选 if k sort: continue # 处理data字段的无上限特殊逻辑对应无限套餐1000G if k data and v[value] 无上限: if r[k] ! 1000: select False break # 处理带操作符的条件如 price 100 if isinstance(v, dict) and operator in v: if not eval(f{r[k]} {v[operator]} {v[value]}): select False break # 普通等值匹配条件 elif str(r[k]) ! str(v): select False break # 所有条件都满足加入结果列表 if select: records.append(r) # 如果结果数量≤1直接返回无需排序 if len(records) 1: return records # 处理排序逻辑默认按price升序 key price reverse False if sort in kwargs: key kwargs[sort][value] reverse kwargs[sort][ordering] descend # 按指定字段和排序方式返回结果 return sorted(records, keylambda x: x[key], reversereverse) class DialogManager: def __init__(self, prompt_templates): # 初始化对话状态、会话历史 self.state {} self.session [ { role: system, content: 你是一个手机流量套餐的客服代表你叫小瓜。可以帮助用户选择最合适的流量套餐产品。 } ] # 初始化各个模块 self.nlu NLU() self.dst DST() self.db MockedDB() # 提示词模板推荐/未找到两种场景 self.prompt_templates prompt_templates def _wrap(self, user_input, records): 根据查询结果拼接给ChatGPT的提示词 if records: # 有匹配结果使用推荐模板 prompt self.prompt_templates[recommand].replace(__INPUT__, user_input) # 用第一条匹配结果填充模板中的占位符如__NAME__、__PRICE__ r records[0] for k, v in r.items(): prompt prompt.replace(f__{k.upper()}__, str(v)) else: # 无匹配结果使用未找到模板 prompt self.prompt_templates[not_found].replace(__INPUT__, user_input) # 用对话状态填充模板中的占位符如__PRICE__、__DATA__ for k, v in self.state.items(): if isinstance(v, dict) and operator in v: # 处理带操作符的条件如 price 100 prompt prompt.replace(f__{k.upper()}__, f{v[operator]}{str(v[value])}) else: # 普通字段直接替换 prompt prompt.replace(f__{k.upper()}__, str(v)) return prompt def _call_chatgpt(self, prompt, modelgpt-3.5-turbo): 调用ChatGPT生成回复 # 深拷贝会话历史避免污染原始数据 session copy.deepcopy(self.session) # 添加用户当前提示词 session.append({role: user, content: prompt}) # 调用API response client.chat.completions.create( modelmodel, messagessession, temperature0, ) # 返回模型生成的回复 return response.choices[0].message.content def run(self, user_input): 对话系统主流程串联所有模块 # 1. 调用NLU解析用户输入得到结构化语义 semantics self.nlu.parse(user_input) print(semantics) print(semantics) # 2. 调用DST更新对话状态 self.state self.dst.update(self.state, semantics) print(state) print(self.state) # 3. 调用MockedDB根据对话状态查询匹配的套餐 records self.db.retrieve(**self.state) # 4. 拼接给ChatGPT的提示词 prompt_for_chatgpt self._wrap(user_input, records) print(gpt-prompt) print(prompt_for_chatgpt) # 5. 调用ChatGPT生成自然语言回复 response self._call_chatgpt(prompt_for_chatgpt) # 6. 将当前对话添加到会话历史用于上下文记忆 self.session.append({role: user, content: user_input}) self.session.append({role: assistant, content: response}) return response解析NLU自然语言理解把人话 → JSONDST对话状态追踪记住用户所有要求MockedDB模拟数据库DialogManager对话管理串联所有模块demo6加入模板通过这种方式可以在特定的场景固定回答模板#加入制定情况下的回答模板 prompt_templates{ recommand:用户说_INPUT_\n\n向用户介绍如下产品_NAME_月费_PRICE_元每月流量_DATA_G, not_found:用户说_INPUT_\n\n没有找到满足_PRICE_元价位_DATA_G流量的产品询问用户知否有其他选择倾向 } dmDialogManager(prompt_templates) responsedm.run(300太贵了200元以内有吗) print(response)demo7增加约束通过 ext 变量添加风格约束控制回复的语气和格式#增加约束改变语气 ext需要口语、亲切一些。不用说“抱歉”。直接回答用户问题并且不需要在前面加自己的身份NO COMMENTS.NO ACKNOW prompt_templates{k:vext for k,v in dm.state.items()} dmDialogManager(prompt_templates)用OpenAI API实现import json from openai import OpenAI from dotenv import load_dotenv,find_dotenv _load_dotenv(find_dotenv()) def print_json(json_source): 把任意对象或数组用排版美观的 JSON 格式打印出来 json_string if (not isinstance(json_source, list)): json_source json.loads(json_source.model_dump_json()) print(json.dumps( json_source, indent4, ensure_asciiFalse )) client OpenAI() # 定义消息历史。先加入 system 消息里面放入对话内容以外的 prompt messages [ { role: system, content: 你是一个手机流量套餐的客服代表你叫小瓜。可以帮助用户选择最合适的流量套餐产品。可以选择的套餐包括 经济套餐月费50元10G流量 畅游套餐月费180元100G流量 无限套餐月费300元1000G流量 校园套餐月费150元200G流量仅限在校生。 } ] def get_completion(prompt, modelgpt-3.5-turbo): # 把用户输入加入消息历史 messages.append({role: user, content: prompt}) response client.chat.completions.create( modelmodel, messagesmessages, temperature0, ) msg response.choices[0].message.content # 把模型生成的回复加入消息历史。很重要否则下次调用模型时模型不知道上下文 messages.append({role: assistant, content: msg}) return msg get_completion(有没有土豪套餐) get_completion(多少钱) get_completion(给我办一个) print_json(messages) #我们发给大模型的prompt不会改变大模型的参数 1.多轮对话需要每次都把绥化历史带上很耗费token 2.对话历史数据可能会被用去训练大模型 进阶思维链提问时以[Let’s think step by step]开头ai会把问题分解为多个步骤ai生成更多相关内容构成更丰富的[上文],从而提高[下文]的正确概率自洽性思维树思考prompt设计和优化方式1.明确目标例目标不明确天气变化的影响目标明确天气变化的主要原因以及对农业、农产品有什么样的影响2.提供上下文例无上下文解释一下微积分有上下文:我是一名高中生目前正在学习微积分请用通俗的语言解释一下微积分的基本概念3.使用具体指示例模糊指示写一篇文章具体提示请写一篇关于人工智能在医疗领域的应用文章包括以下几点应用场景、有事和挑战4.提供示例例无示例生成一个关于产品的报告有示例生成一个关于产品的报告格式如下\n\n-产品名称\n-价格\n-特点\n-优点\n-缺点5.使用分步指示对于复杂的任务分解为多个步骤逐步引导模型完成6.控制输出长度7.使用占位符和模板8.制定输出格式9.使用多轮对话10.反复实验以及调整优化总结使用prompt先拆解步骤再具体描述小步骤通过反复尝试优化prompt各个环节严谨同时应多维度进行考虑