LangChain: Message封装和Prompt封装

  本篇博客主要介绍Langchain中的Message和Prompt封装

1. Message封装

1.1 Messages

  Messages对象可以用在提示词和聊天信息中。目前主要有MessageMessageChunk两种类型,这里仅以Message类为主进行介绍。Message类主要有以下几种:

  • AIMessage: 大模型返回的信息,类似于OpenAI模型中assistant类型的消息。
  • ChatMessage: ChatMessage有一个role字段,用于标识消息发送者的角色或类型。
  • FunctionMessage/ToolMessage:向LLM返回函数或工具得到的信息。FunctionMessage是ToolMessage的旧版本。
  • SystemMessage: 系统角色信息,类似于OpenAI模型中system类型的消息。
  • HumanMessage:用户角色的信息,类似于OpenAI模型中user类型的消息。

关于Message类信息其用法举例如下(目前只能用到content参数):

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage,SystemMessage,ToolMessage
from dotenv import load_dotenv,find_dotenv
_=load_dotenv(find_dotenv())
client=ChatOpenAI(
    model_kwargs={"tools":[{ 
            "type": "function",
            "function": {
                "name": "sum",
                "description": "加法器,计算一组数的和",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "numbers": {"type": "array", "items": { "type": "number"}}
                    }
                }
            }
        }]})
messages=[
    SystemMessage(content="你是一个数学家,可以计算所有整数的和。"),
    HumanMessage(content="请计算12343、4363、984773这三个整数的和"),
]
response=client.invoke(messages)
#response的类型为AIMessage类型
if response.additional_kwargs['tool_calls']:
    tool=response.additional_kwargs['tool_calls'][0]
    arguments=eval(tool['function']['arguments'])
    fun_message=ToolMessage(
        content=str(sum(arguments['numbers'])),
        tool_call_id=tool['id'])
    #ToolMessage向大模型返回function calling执行的结果
    messages.extend([response,fun_message])
    response2=client.invoke(messages)
    print(response2)

其执行结果如下(返回的类型是AIMessage类型):

content='这三个整数的和为1001479。' response_metadata={'token_usage': {'completion_tokens': 13, 'prompt_tokens': 114, 'total_tokens': 127}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-38d36c7c-3b4f-49a9-9711-4b6d79347311-0'

注意,只有使用Chat模型的时候才会输出上述结果。
当模型采用流式输出时会返回MessageChunk类型,具体举例如下:

prompt=PromptTemplate.from_template("输出1到{max_value}之间的所有整数。每个数字之间用逗号,分隔。")
llm=ChatOpenAI(model_kwargs={"stream":True})
stream_chain=prompt|llm
for chunk in stream_chain.stream({"max_value":"4"}):
    print(chunk)

其执行结果展示如下:

content='' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content='1' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content=',' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content=' ' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content='2' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content=',' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content=' ' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content='3' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content=',' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content=' ' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content='4' id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'
content='' response_metadata={'finish_reason': 'stop'} id='run-d90bbeb4-ff10-491a-9a86-953ce08dbdf6'

2. Prompts封装

   Prompt提示通常由多个组件和提示值构成。Langchain提供的prompt子类可以在以下页面上查询到: https://api.python.langchain.com/en/latest/core_api_reference.html#module-langchain_core.prompts 。这里按照这些prompt的父类的分类分别介绍:

2.1 StringPromptTemplate类

  StringPromptTemplate类主要包括以下几种prompt类:PromptTemplateFewShotPromptTemplateFewShotPromptWithTemplates

2.1.1 PromptTemplate类

  这里先来看PromptTemplate类的基本用法。PromptTemplate的方法主要有以下(这里不会介绍所有方法):

  • from_examplesfrom_filefrom_template。这三个是类方法,主要用来生成提示词模板PromptTemplate(提示词模板中存在未被替换的变量)。具体用法举例如下:
from langchain_core.prompts import PromptTemplate
prompt_temp1=PromptTemplate.from_template(template="""
你是一个专业的翻译官,现在你需要将以下英文文本翻译成中文:
{text}
""",template_format="f-string")
print(prompt_temp1)
prompt_temp2=PromptTemplate.from_file("./test_langchain/template.txt")
print(prompt_temp2)
prompt_temp3=PromptTemplate.from_examples(
    examples=[r"{text}\n"],
    suffix="用Markdown格式输出",
    prefix="你会一个专业的翻译官,现在你需要将以下英文文本翻译成中文:",
    input_variables=["text"]
)
print(prompt_temp3)

其输出结果如下:

input_variables=['text'] template='\n你是一个专业的翻译官,现在你需要将以下英文文本翻译成中文:\n{text}\n'
input_variables=['text'] template='你是一个专业的翻译官,现在你需要将以下英文文本翻译成中文:\n{text}'
input_variables=['text'] template='你会一个专业的翻译官,现在你需要将以下英文文本翻译成中文:\n\n{text}\\n\n\n用Markdown格式输出'

Tips:如果提示词模板中没有待填充的变量,就尽量不要使用提示词模板类

  • format_promptformat:将PromptTemplate模板中的变量填充生成正式的提示词(但是返回值类型不同)。这个方法还有同作用的异步方法aformataformat_prompt
from langchain_core.prompts import PromptTemplate
import asyncio
prompt_temp=PromptTemplate.from_template(template="""
你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:
{text}
请翻译成中文,并输出为Markdown格式。
""",template_format="f-string")
#template_format还可以接受jinja2类型
prompt1=prompt_temp.format(text="hello world")
print(prompt1)
prompt2=prompt_temp.format_prompt(text="good morning")
print(prompt2)
##async方法
prompt_temp=PromptTemplate.from_template(template="""
你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:
{text}
请翻译成中文,并输出为Markdown格式。
""",template_format="f-string")
#template_format还可以接受jinja2类型
async def prompt_format():
    prompt1=await prompt_temp.aformat(text="hello world")
    prompt2=await prompt_temp.aformat(text="good morning")
    print(prompt1)
    print(prompt2)
asyncio.run(prompt_format())

其结果如下:

你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:
hello world
请翻译成中文,并输出为Markdown格式。
text='\n你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:\ngood morning\n请翻译成中文,并输出为Markdown格式。\n'
你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:
hello world
请翻译成中文,并输出为Markdown格式。

你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:
good morning
请翻译成中文,并输出为Markdown格式。
  • invoke:与format方法相比,当用户需要创建链的时候,并且这个链的一部分涉及到使用提示模板时,则可以使用该方法。 invoke不仅仅可以格式化字符串,还可以处理输入、输出和其他复杂的逻辑。具体举例如下(运行结果不展示):
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
from dotenv import load_dotenv,find_dotenv
_=load_dotenv(find_dotenv())
template=PromptTemplate.from_template(template="""
你是一个专业的翻译官,现在需要你帮助翻译以下英文文本:
{text}
请翻译成中文,并输出为Markdown格式。
""",template_format="f-string")
llm=OpenAI()
chain = template|llm
print(chain.invoke("hello world"))
  • batchbatch_as_completed:这两个方法都用于批量处理多个输入数据,并且每个输入数据使用invoke方法执行,但二者略有不同。batch使用thread线程池执行,而batch_as_completed方法当每个输入数据处理完成后立即返回结果。这种方法适用于输入数据量较大或希望逐步处理并获取结果的场景。它可以提高处理效率,尤其是在处理时间较长的任务时。同时这两个方法也有async类方法。其用法举例如下:
from langchain.prompts import PromptTemplate
template = PromptTemplate(
    input_variables=["location", "activity"],
    template="What is the best time to visit {location} for {activity}?"
)
inputs = [
    {"location": "Paris", "activity": "sightseeing"},
    {"location": "New York", "activity": "shopping"},
    {"location": "Tokyo", "activity": "cultural experiences"}
]
batch_results = template.batch(inputs)
for result in batch_results:
    print(result)

其结果如下:

text='What is the best time to visit Paris for sightseeing?'
text='What is the best time to visit New York for shopping?'
text='What is the best time to visit Tokyo for cultural experiences?'
  • partial该方法可以对提示词模板进行部分填充,该方法可以帮助用户逐步构建最终的提示词模板。注意该方法返回的仍是提示词模板,其用法举例如下:
from langchain_core.prompts import PromptTemplate

template=PromptTemplate(template="{name},{age}",
                        input_variables=["name","age"],)
print(template)
template=template.partial(name="John")
print(template)
template=template.format(age=30)
print(template)

其结果如下:

input_variables=['age', 'name'] template='{name},{age}'
input_variables=['age'] partial_variables={'name': 'John'} template='{name},{age}'
John,30
2.1.2 FewShotPromptTemplate类

  FewShotPromptTemplate类是LangChain内置的一个少样本提示词模板类,其独特之处在于支持动态添加示例和选择器。其用法举例如下:

from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
samples = [  
    {"flower_type": "玫瑰", "occasion": "浪漫", "ad_copy": "玫瑰,象征着浪漫,是你向心爱的人表达爱意的最佳选择"},  
    {"flower_type": "康乃馨", "occasion": "母亲节", "ad_copy": "康乃馨,代表着孝心,是献给母亲最好的礼物"},  
]
example_prompt = PromptTemplate(  
    input_variables=["flower_type", "occasion", "ad_copy"],  
    template="鲜花类型: {flower_type} 场合: {occasion} 广告文案: {ad_copy}"  
)  
few_shot_prompt_template = FewShotPromptTemplate(  
    examples=samples,  
    example_prompt=example_prompt,  # 如果不需要自定义示例模板,也可以省略  
    prefix="以下是一些鲜花广告文案的示例:\n",  
    suffix="现在,请为以下鲜花类型和场合生成广告文案:\n鲜花类型: {flower_type} 场合: {occasion} 广告文案:",  
    input_variables=["flower_type", "occasion"]  
)

few_shot_prompt=few_shot_prompt_template.format(flower_type="红玫瑰", occasion="情人节")
print(few_shot_prompt)

其执行结果如下:

以下是一些鲜花广告文案的示例:


鲜花类型: 玫瑰 场合: 浪漫 广告文案: 玫瑰,象征着浪漫,是你向心爱的人表达爱意的最佳选择

鲜花类型: 康乃馨 场合: 母亲节 广告文案: 康乃馨,代表着孝心,是献给母亲最好的礼物

现在,请为以下鲜花类型和场合生成广告文案:
鲜花类型: 红玫瑰 场合: 情人节 广告文案:

2.2 BaseStringMessagePromptTemplate类

  BaseStringMessagePromptTemplate的主要包括以下几种prompt子类:ChatMessagePromptTemplateHumanMessagePromptTemplateAIMessagePromptTemplateSystemMessagePromptTemplate。这几种prompt类经过值填充后会生成Message类数据。其用法举例如下(以千问大模型为例):

from langchain_community.chat_models import ChatTongyi
from langchain.schema import SystemMessage,AIMessage
from langchain_core.prompts import (ChatMessagePromptTemplate,
                                    HumanMessagePromptTemplate,
                                    PromptTemplate)
ChatMessage=ChatMessagePromptTemplate(role='system',prompt=PromptTemplate.from_template('{content}'))
sys_msg = ChatMessage.format(content="你是一个客服助手,你叫小爱。")
usr_template = HumanMessagePromptTemplate.from_template("{usr_question}")
usr_msg=usr_template.format(usr_question="你是谁?")
chat_Model=ChatTongyi(model_name="qwen-turbo")
messages=[sys_msg,usr_msg]
res=chat_Model.invoke(messages)
print(res.content)

其返回结果如下:

我是小爱,一个客服助手,专门在这里为您提供帮助和解答问题。有什么可以帮到您的吗?

2.3 PipelinePromptTemplate类

  PipelinePromptTemplate类可以组合不同的提示词模板,在希望重用部分提示词的时非常有效。其用法举例如下:

from langchain_core.prompts import PromptTemplate,PipelinePromptTemplate

ask_name_prompt = PromptTemplate(
    template="What is your name?,my name is {name}",
    input_variables=[]
)
# 定义第二个提示模板,根据用户的名字进行问候
greet_user_prompt = PromptTemplate(
    template="Hello, {name}! How can I assist you today?",
    input_variables=["name"]
)
final_prompt=PromptTemplate(template="{user},\n{greet}",input_variables=["name","greet"])
# 将这两个提示连接成一个 PipelinePrompt
pipeline_prompt = PipelinePromptTemplate(
    pipeline_prompts=[("user",ask_name_prompt),
                      ("greet",greet_user_prompt)],
    final_prompt=final_prompt
)
print(pipeline_prompt.format(name="Alice"))

其结果如下:

What is your name?,my name is Alice,
Hello, Alice! How can I assist you today?
### 回答1: 首先, 需要申请并获取 OpenAI API 的 key, 然后安装 OpenAI 的 python SDK (openai). 接下来, 可以使用 SDK 中提供的方法调用 OpenAI API 实现问答功能。具体地, 可以使用 openai.Completion.create() 方法调用 "Davinci" 模型进行问答。参数需要传递问题文本 (prompt) 和可选参数 (如 temperature, max_tokens等)。 获取到结果之后, 可以使用 python 对结果进行处理和展示, 以实现一个简单的问答程序。 下面是一个简单的例子: ``` import openai openai.api_key = "YOUR_API_KEY" prompt = "What is the capital of France?" completions = openai.Completion.create( engine="davinci", prompt=prompt, max_tokens=1024, temperature=0.7, ) message = completions.choices[0].text print(message) ``` 这样你就能使用openai的api 来封装一个问答程序了 ### 回答2: 要使用Python和OpenAI API封装一个问答程序,可以按照以下步骤进行: 1. 导入必要的Python库和OpenAI的Python SDK:首先,我们需要导入必要的Python库,如`openai`、`json`等。同时,确保已安装OpenAI的Python SDK,可以通过`pip install openai`安装。 2. 设置OpenAI API密钥:在程序中,需要设置OpenAI API的访问密钥,以便进行API调用。密钥可以从OpenAI网站上获得。 3. 编写代码实现问答功能: - 创建一个函数或类,以便重用和调用问题和答案的逻辑。 - 在函数中,使用OpenAI的`openai.Completion.create()`方法调用问答模型API。 - 将问题作为输入传递给API,并配置相关参数,如`engine`、`temperature`和`max_tokens`等。 - 获取API返回的答案,并返回给调用者。 下面是一个简单的例子来说明上述过程: ```python import openai import json # 设置OpenAI API密钥 openai.api_key = 'your_openai_api_key' # 封装一个问答函数 def ask_question(question): # 调用问答模型API response = openai.Completion.create( engine='davinci-codex', # 指定API使用的模型 prompt=question, # 设置输入问题 max_tokens=100, # 设置最大返回标记数 temperature=0.7 # 设置温度,控制生成答案的多样性 ) # 提取答案 answer = response.choices[0].text.strip() return answer # 测试问答功能 question = "你是谁?" answer = ask_question(question) print(f"问题: {question}") print(f"答案: {answer}") ``` 在上述例子中,我们使用了一个名为`davinci-codex`的模型来回答问题,可以根据需要选择适合自己需求的模型。注意,OpenAI API使用计费模式,需要根据使用情况来计算费用。 这只是一个简单的例子,你可以根据自己的需求对问答程序进行更复杂和灵活的封装。 ### 回答3: 要使用Python和OpenAI API封装一个问答程序,可以按照以下步骤进行: 1. 导入必要的库:首先需要安装OpenAI API的Python包,并导入相关库,例如openai和json。 2. 设置API密钥:在OpenAI网站上创建账户并获取API密钥。将密钥设置为环境变量或直接在代码中保存。 3. 初始化OpenAI API:使用导入的openai库来初始化OpenAI API,使用API密钥作为参数。 4. 输入问题和文本:定义一个函数,接收用户提出的问题和相关文本。将问题和文本作为参数传递给OpenAI API。 5. 发送API请求:使用openai库中的函数来发送API请求,将问题和文本发送给OpenAI模型进行处理。 6. 处理API响应:从API响应中提取答案。API的响应以JSON格式返回,可以使用json库解析响应。 7. 输出答案:将提取到的答案返回给用户。 以下是一个简单的代码示例: ```python import openai import json # 设置OpenAI API密钥 openai.api_key = 'YOUR_API_KEY' # 初始化OpenAI def init_openai(): openai.api_key = 'YOUR_API_KEY' # 执行问答 def ask_question(question, text): # 发送API请求 response = openai.Completion.create( engine='davinci', prompt=question + '\nText: ' + text + '\nQuestion:', max_tokens=100, n=1, stop=None, temperature=0.7 ) # 处理API响应 answer = response.choices[0].text.strip().split('Answer: ')[1] return answer # 例子 def main(): # 初始化OpenAI init_openai() # 输入问题和文本 question = 'What is the capital of France?' text = 'France is a beautiful country located in Europe.' # 执行问答 answer = ask_question(question, text) # 输出答案 print(answer) if __name__ == '__main__': main() ``` 以上代码中的`YOUR_API_KEY`需要替换为你自己在OpenAI网站上获得的API密钥。`question`和`text`表示用户输入的问题和相关文本。可以根据需要进行进一步的优化和错误处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值