青训营X豆包MarsCode AI训练营5-11课 | 豆包MarsCode AI 刷题

90 阅读4分钟

主要学习了关于提示工程、链和记忆的相关知识,其中发现由于版本问题会一直出现一些警告,按照警告知识了解了一下关于使用|来构建链的方式,此时发现链的调用方式减少为只能使用invoke来进行调用,且记录的笔记代码都经过了化简

# 创建LLMChain
 llm_chain = PromptTemplate.from_template(template) | llm | StrOutputParser() # RunnableSequence
 result = llm_chain.invoke({"xxx": "hello"})

以下为教材以及老版本中的创建LLMChain方式以及包含多个调用方式,后续的学习还是主要以下面老版本方式为主  

 llm_chain = LLMChain(llm=llm, prompt=PromptTemplate.from_template(template))
 result = llm_chain("hello") # 老版本返回json格式

提示工程

提示框架,LangChain中提供String(StringPromptTemplate)和Chat(BaseChatPromptTemplate)两种基本类型模板

  • 指令instruction:告诉模型任务做啥,怎么做
  • 上下文context:额外知识来源
  • 提示输入prompt input:具体问题变量
  • 输出指示器output indicator:标记要生成的文本的开始

提示模版类型

① PromptTemplate

 from langchain import PromptTemplate
 # 常用String提示模版
 template = """xx{product}xxx"""
 prompt = PromptTemplate.from_template(template)
 print(prompt.format(product="input_something"))
 ​
 # 提示模板类的构造函数
 prompt = PromptTemplate(
     input_variables=["test1", "test2"], 
     template="你是xxx, 对于{test1}的{test2}, xxx?"
 )
 print(prompt.format(test1="xx", test2="xx"))

② ChatPromptTemplate

 # 常用Chat提示模板, 组合各种角色消息模板
 ​
 # 模板的构建
 system_template = "xx{product}xx"
 system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
 ​
 human_template = "xxx{product_detail}。"
 human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
 ​
 prompt_template = ChatPromptTemplate.from_messages(
     [system_message_prompt, human_message_prompt]
 )
 ​
 # 格式化提示消息生成提示
 prompt = prompt_template.format_prompt(
     product="xxx", product_detail="xxx"
 ).to_messages()

③ FewShotPromptTemplate

  • 少样本提示模板,模仿示例写出新文案
  • Few-Shot(少样本)、One-Shot(单样本)、 Zero-Shot(零样本):让机器学习模型在极少量甚至无示例情况下学习到新概念或类别
 # 创建示例样本
 samples = [
     {
         "key1": "xx",
         "key2": "yy"
     },
     {
         "key1": "zz",
         "key2": "qq"
     }
 ]
 ​
 # 创建提示模板
 template="键1: {key1}\n 键2: {key2}"
 prompt_sample = PromptTemplate(input_variables=["key1", "key2"], template = template)
 ​
 # 创建FewShotPromptTemplate对象
 prompt = FewShotPromptTemplate(
     examples = samples,
     example_prompt=prompt_sample,
     suffix="{key1}{key2}",
     input_variables=["key1", "key2"]
 )

CoT

  • 思维链,Chain of Thought,用于引导模型推理
  • Few-Shot CoT提示中提供CoT示例,Zero-Shot CoT让模型一步一步思考
 cot_template = """将包含一些对话推导示例"""
 system_prompt_cot = SystemMessagePromptTemplate.from_template(cot_template)

TOT

  • 思维树,Tree of Thoughts
  • 为任务定义具体思维步骤及每个步骤候选项数量

个人觉得就是嵌套了多个链,感觉后续要学习的话,需要尽可能去学习相关的源码,收获应该会更大

调用

老版本存在多种调用

 result = llm_chain(dict) # __call__直接调用
 llm_chain.run() # run调用
 result = llm_chain.predict(xx="xx") # predict调用
 result = llm_chain.apply([{dict},{dict},{dict}])# 针对输入列表apply调用, 返回字符串
 result = llm_chain.generate(input_list)# 返回LLMResult对象

LLMChain

将提示词模板、语言模型、输出解析封装成链接口

 from langchain_core.output_parsers import StrOutputParser
 template = "{xxx}是?"
 llm = OpenAI(temperature=0)
 # 创建LLMChain
 llm_chain = PromptTemplate.from_template(template) | llm | StrOutputParser() # RunnableSequence
 result = llm_chain.invoke({"xxx": "hello"}) # 只能使用invoke调用
 ​
 #llm_chain = LLMChain(llm=llm, prompt=PromptTemplate.from_template(template))
 #result = llm_chain("hello") 老版本返回json格式
 print(result)

顺序链

Sequential Chain,将多个链串联

 # 创建多个LLMChain
 first_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="c") # 生成c作为后续输入
 # 这是总的链,我们按顺序运行这三个链
 overall_chain = SequentialChain(
     chains=[first_chain, second_chain, third_chain],
     input_variables=["a", "b"], # 直接输入
     output_variables=["c","d","e"], # 由chat生成输入后续链中
     verbose=True)
 ​
 result = overall_chain({"a":"x", "b": "y"})

路由链

  • 动态选择用于给定输入的下一个链,否则发入默认链
  • 构建两个场景的模板
 a_case_template = """你是a, 需要你回答:{input}"""
 b_case_template = """你是b, 需要你回答:{input}"""
 ​
 # 提示信息
 prompt_infos = [
     {"key": "a", "description": "a问题", "template": a_case_template,},
     {"key": "b", "description": "b问题", "template": b_case_template,}]
  • 每个场景构建目标链
 chain_map = {}
 for info in prompt_infos:
     prompt = ...
     chain = ...
     chain_map[info["key"]] = chain
  • 构建路由链
 from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
 from langchain.chains.router.multi_prompt_prompt import (
     MULTI_PROMPT_ROUTER_TEMPLATE as RounterTemplate,
 )
 ​
 destinations = [f"{p['key']}: {p['description']}" for p in prompt_infos]
 # 路由模板
 router_template = RounterTemplate.format(destinations="\n".join(destinations))
 ​
 # 根据模板生成路由提示
 router_prompt = PromptTemplate(
     template=router_template,
     input_variables=["input"],
     output_parser=RouterOutputParser(),
 )
 router_chain = LLMRouterChain.from_llm(llm, router_prompt, verbose=True)
  • 构建默认对话链
 from langchain.chains import ConversationChain
 default_chain = ConversationChain(llm=llm, 
                                   output_key="text",
                                   verbose=True)
  • 构建多提示链
 from langchain.chains.router import MultiPromptChain
 ​
 chain = MultiPromptChain(
     router_chain=router_chain,
     destination_chains=chain_map,
     default_chain=default_chain,
     verbose=True,
 )

运行

 chain.run("如何xxx?")

记忆

  • 通过{history}参数将历史对话信息存储在提示模板中,作为新的提示内容
 conversation = ConversationChain(llm=llm, memory=ConversationBufferMemory()) 
 # 缓冲记忆 conversation.memory.buffer 中存储

缓冲窗口记忆

ConversationBufferWindowMemory,只保存最近窗口值的互动,限制使用的Token数

 conversation = ConversationChain(
     llm=llm,
     memory=ConversationBufferWindowMemory(k=1)
 )

对话总结记忆

ConversationSummaryMemory,由另一个llm汇总传递给history

 conversation = ConversationChain(
     llm=llm,
     memory=ConversationSummaryMemory(llm=llm)
 )

对话总结缓冲记忆

ConversationSummaryBufferMemory,混合记忆,总结早期互动,保留最近互动

 conversation = ConversationChain(llm=llm, memory=ConversationBufferWindowMemory(k=1))