第四节模型I/0学习笔记 | 豆包MarsCode AI刷题

174 阅读8分钟

一、基础知识点

(一)Model I/O

模型的使用过程可以拆解成三块,分别是输入提示(对应图中的Format)、调用模型(对应图中的Predict)和输出解析(对应图中的Parse)。这三块形成了一个整体,因此在LangChain中这个过程被统称为 Model I/O(Input/Output)。

(二)提示模板

提示模板生成方式

# 导入LangChain中的提示模板
from langchain.prompts import PromptTemplate
# 创建原始模板
template = """您是一位专业的鲜花店文案撰写员。\n
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
"""
# 根据原始模板创建LangChain提示模板
prompt = PromptTemplate.from_template(template) 
# 打印LangChain提示模板的内容
print(prompt)

提示模板具体内容

input_variables=['flower_name', 'price'] 
output_parser=None partial_variables={} 
template='/\n您是一位专业的鲜花店文案撰写员。
\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n'
template_format='f-string' 
validate_template=True

(三)语言模型

# 设置OpenAI API Key
import os
os.environ["OPENAI_API_KEY"] = '你的Open AI API Key'

# 导入LangChain中的OpenAI模型接口
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
# 输入提示
input = prompt.format(flower_name=["玫瑰"], price='50')
# 得到模型的输出
output = model.invoke(input)
# 打印输出内容
print(output)  

input = prompt.format(flower_name=["玫瑰"], price='50') 这行代码的作用是将模板实例化,此时将 {flower_name} 替换为 "玫瑰"{price} 替换为 '50',形成了具体的提示:“您是一位专业的鲜花店文案撰写员。对于售价为 50 元的玫瑰,您能提供一个吸引人的简短描述吗?”

提示模板➕语言模型

# 导入LangChain中的提示模板
from langchain import PromptTemplate
# 创建原始模板
template = """您是一位专业的鲜花店文案撰写员。\n
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
"""
# 根据原始模板创建LangChain提示模板
prompt = PromptTemplate.from_template(template) 
# 打印LangChain提示模板的内容
print(prompt)

# 设置OpenAI API Key
import os
os.environ["OPENAI_API_KEY"] = '你的Open AI API Key'

# 导入LangChain中的OpenAI模型接口
from langchain import OpenAI
# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')

# 多种花的列表
flowers = ["玫瑰", "百合", "康乃馨"]
prices = ["50", "30", "20"]

# 生成多种花的文案
for flower, price in zip(flowers, prices):
    # 使用提示模板生成输入
    input_prompt = prompt.format(flower_name=flower, price=price)

    # 得到模型的输出
    output = model.invoke(input_prompt)

    # 打印输出内容
    print(output)

直接使用Open AI API

import openai # 导入OpenAI
openai.api_key = 'Your-OpenAI-API-Key' # API Key

prompt_text = "您是一位专业的鲜花店文案撰写员。对于售价为{}元的{},您能提供一个吸引人的简短描述吗?" # 设置提示

flowers = ["玫瑰", "百合", "康乃馨"]
prices = ["50", "30", "20"]

# 循环调用Text模型的Completion方法,生成文案
for flower, price in zip(flowers, prices):
    prompt = prompt_text.format(price, flower)
    response = openai.completions.create(
        engine="gpt-3.5-turbo-instruct",
        prompt=prompt,
        max_tokens=100
    )
    print(response.choices[0].text.strip()) # 输出文案

使用其他模型(HuggingFaceHub中的开源模型T5)

# 导入LangChain中的提示模板
from langchain.prompts import PromptTemplate
# 创建原始模板
template = """You are a flower shop assitiant。\n
For {price} of {flower_name} ,can you write something for me?
"""
# 根据原始模板创建LangChain提示模板
prompt = PromptTemplate.from_template(template) 
# 打印LangChain提示模板的内容
print(prompt)
import os
os.environ['HUGGINGFACEHUB_API_TOKEN'] = '你的HuggingFace API Token'
# 导入LangChain中的OpenAI模型接口
from langchain_community.llms import HuggingFaceHub
# 创建模型实例
model= HuggingFaceHub(repo_id="google/flan-t5-large")
# 输入提示
input = prompt.format(flower_name=["rose"], price='50')
# 得到模型的输出
output = model(input)
# 打印输出内容
print(output)

使用LangChain和提示模板的好处是:

  1. 代码的可读性:使用模板的话,提示文本更易于阅读和理解,特别是对于复杂的提示或多变量的情况。
  2. 可复用性:模板可以在多个地方被复用,让你的代码更简洁,不需要在每个需要生成提示的地方重新构造提示字符串。
  3. 维护:如果你在后续需要修改提示,使用模板的话,只需要修改模板就可以了,而不需要在代码中查找所有使用到该提示的地方进行修改。
  4. 变量处理:如果你的提示中涉及到多个变量,模板可以自动处理变量的插入,不需要手动拼接字符串。
  5. 参数化:模板可以根据不同的参数生成不同的提示,这对于个性化生成文本非常有用。

(四)输出解析

通过LangChain的输出解析器重构程序

# 导入OpenAI Key
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'

# 导入LangChain中的提示模板
from langchain.prompts import PromptTemplate
# 创建原始提示模板
prompt_template = """您是一位专业的鲜花店文案撰写员。
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
{format_instructions}"""

# 通过LangChain调用模型
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')

# 导入结构化输出解析器和ResponseSchema
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
# 定义我们想要接收的响应模式
response_schemas = [
    ResponseSchema(name="description", description="鲜花的描述文案"),
    ResponseSchema(name="reason", description="问什么要这样写这个文案")
]
# 创建输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

# 获取格式指示
format_instructions = output_parser.get_format_instructions()
# 根据原始模板创建提示,同时在提示中加入输出解析器的说明
prompt = PromptTemplate.from_template(prompt_template, 
                partial_variables={"format_instructions": format_instructions}) 

# 数据准备
flowers = ["玫瑰", "百合", "康乃馨"]
prices = ["50", "30", "20"]

# 创建一个空的DataFrame用于存储结果
import pandas as pd
df = pd.DataFrame(columns=["flower", "price", "description", "reason"]) # 先声明列名

for flower, price in zip(flowers, prices):
    # 根据提示准备模型的输入
    input = prompt.format(flower_name=flower, price=price)

    # 获取模型的输出
    output = model.invoke(input)
    
    # 解析模型的输出(这是一个字典结构)
    parsed_output = output_parser.parse(output)

    # 在解析后的输出中添加“flower”和“price”
    parsed_output['flower'] = flower
    parsed_output['price'] = price

    # 将解析后的输出添加到DataFrame中
    df.loc[len(df)] = parsed_output  

# 打印字典
print(df.to_dict(orient='records'))

# 保存DataFrame到CSV文件
df.to_csv("flowers_with_descriptions.csv", index=False)

LangChain框架的好处

  1. 模板管理:在大型项目中,可能会有许多不同的提示模板,使用 LangChain 可以帮助你更好地管理这些模板,保持代码的清晰和整洁。
  2. 变量提取和检查:LangChain 可以自动提取模板中的变量并进行检查,确保你没有忘记填充任何变量。
  3. 模型切换:如果你想尝试使用不同的模型,只需要更改模型的名称就可以了,无需修改代码。
  4. 输出解析:LangChain的提示模板可以嵌入对输出格式的定义,以便在后续处理过程中比较方便地处理已经被格式化了的输出。

二、学习心得

在深入学习了“第四节模型I/O”的基础知识点后,我对如何使用LangChain框架结合不同的语言模型进行文本生成有了更为全面的理解。以下是我本次学习的几点深刻体会:

(一)Model I/O流程的理解与掌握

Model I/O的使用过程被清晰地拆解为输入提示、调用模型和输出解析三块。这种流程化的处理方式让我认识到,在处理文本生成任务时,需要有一个清晰的思路和结构。输入提示是引导模型生成所需文本的关键,调用模型则是利用AI的能力进行实际的文本生成,而输出解析则是对生成结果进行后处理,使其更符合实际需求。这种流程化的处理方式不仅提高了工作效率,也保证了文本生成的质量。

(二)提示模板的强大功能

提示模板的引入是本次学习的亮点之一。通过创建原始模板,并利用LangChain框架生成具体的提示文本,我深刻体会到了模板在提高代码可读性、可复用性和维护性方面的巨大优势。特别是在处理包含多个变量的复杂提示时,模板可以自动处理变量的插入,避免了手动拼接字符串的繁琐和易错性。此外,模板的参数化特性也使得个性化生成文本变得更加容易。

(三)不同语言模型的应用与对比

在本次学习中,我尝试了使用OpenAI的GPT模型和HuggingFace Hub中的T5模型进行文本生成。通过对比不同模型的输出,我发现它们在生成文本的风格、流畅度和准确性方面存在差异。这让我意识到,在选择模型时需要根据具体任务的需求进行权衡和选择。同时,LangChain框架提供的模型切换功能也让我能够轻松地在不同模型之间进行切换,从而找到最适合当前任务的模型。

(四)输出解析的重要性

输出解析是本次学习的另一个重要内容。通过引入结构化输出解析器和ResponseSchema,我能够更准确地定义期望的输出格式,并对生成结果进行后处理。这不仅提高了输出结果的可用性,也使得后续处理过程变得更加方便和高效。

(五)LangChain框架的便捷性

最后,我要特别提到LangChain框架在模板管理、变量提取和检查、模型切换以及输出解析等方面的便捷性。这些功能不仅提高了我的工作效率,也保证了代码的质量和可维护性。在未来的工作中,我将继续利用LangChain框架进行文本生成任务的处理,并不断探索和尝试新的功能和优化方法。