模型I/O:输入提示、调用模型、解析输出|豆包MarsCode AI刷题

227 阅读8分钟

LangChain六大核心组件之一:Models,作为LangChain框架的发动机。

目标:一个能够自动生成鲜花文案的应用程序。

Model I/O

模型的使用过程

  1. 输入提示(Format)
  2. 调用模型(Predict)
  3. 输出解析(Parse)

Model I/O的每个阶段,LangChain提供了模板和工具,可以快捷地调用各种语言模型的接口。

  1. 提示模板:使用模型的第一个环节是把prompt输入到模型中,可以创建LangChain模板,根据需求动态调整输入。
  2. 语言模型:LangChain允许通过接口调用语言模型,灵活、便利。
  3. 输出解析:通过输出解析器精确地从模型的输出中获取需要的信息,而不需要处理冗余/不相关的数据,还可以把llm返回的非结构化文本转化成程序可处理的结构化数据

提示模板

“提示工程”,Prompt Engineering,研究对llm的提示构建。

具体原则

  1. 给模型清晰明确的指示
  2. 让模型慢慢思考

创建一个简单的LangChain提示模板开始

例:针对指定售价指定种类的鲜花,提供一个简短描述,方便生成销售词。

# 导入LangChain中的提示模板
import os
from langchain.prompts import PromptTemplate
from langchain_community.llms import Tongyi

# 创建原始模板
template = """您是一位专业的鲜花店文案撰写员。\n
对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?
"""

# 根据原始模板创建LangChain提示模板
prompt = PromptTemplate.from_template(template)
# 打印LangChain提示模板的内容
print(prompt)

# DASHSCOPE_API_KEY
os.environ["DASHSCOPE_API_KEY"] = '阿里的DASHSCOPE_API_KEY'
# 创建模型实例
llm = Tongyi(model_name="qwen-chat", api_key=os.environ["DASHSCOPE_API_KEY"])

# 输入提示
input_prompt = prompt.format(price=50, flower_name="玫瑰")
# 打印输入提示
print(input_prompt)
# 得到模型的输出
output = llm.invoke(input_prompt)
# 打印输出内容
print(output)

语言模型

LangChain中支持的模型有三大类。

  1. 大语言模型(llm):Text Model(对应到langchain_community.llms库)。输入:文本字符串;输出:文本字符串。典型的LLM:OpenAI的text-davinci-003、Facebook的LLaMA、ANTHROPIC的Claude。
  2. chat model:主要代表OpenAI的GPT系列模型。模型通常由语言模型支持,API更加结构化。输入:聊天消息列表;输出:聊天消息。
  3. embegging model:输入:文本;输出:浮点数列表。文本嵌入模型如OpenAI的text-embedding-ada-002。模型负责把文档存入向量数据库,和这里说的提示工程关系不大。

复用提示模板,生成多个鲜花的文案。

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

# 设置DASHSCOPE_API_KEY
os.environ["DASHSCOPE_API_KEY"] = '阿里的DASHSCOPE_API_KEY'

# 创建模型实例
llm = Tongyi(model_name="qwen-text", api_key=os.environ["DASHSCOPE_API_KEY"])

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

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

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

    # 打印输出内容
    print(output)
input_variables=['flower_name', 'price'] input_types={} partial_variables={} template='您是一位专业的鲜花店文案撰写员。\n\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n'
【浪漫之选,经典玫瑰】每一朵都承载着爱与祝福,精心挑选的50元经典红玫瑰,色泽鲜艳、花型饱满,是传递心意的最佳使者。无论是表达爱意、庆祝纪念日还是日常小确幸,都能让这份美好瞬间定格,成为彼此心中最温暖的记忆。选择我们,让每一束花都充满故事与情感。
【百合】—— 纯净之爱,30元献上一份高雅祝福

在喧嚣的都市生活中,一束纯净如雪的百合,不仅能够带来一抹清新脱俗的气息,更承载着对美好生活的向往与追求。它象征着纯洁的爱情、真挚的友情以及对未来的无限憧憬。无论是作为节日礼物还是日常问候,这束价值30元的百合都能为您传递最真诚的心意,让接收者感受到来自心底深处的温暖与关怀。选择它,用最低的成本表达最高贵的情感吧!
当然可以,以下是一则关于康乃馨的简短描述:

“献上一束温柔的爱意,每朵精致的康乃馨都承载着对母亲、爱人或朋友最真挚的祝福。细腻的花瓣轻轻摇曳,仿佛在低语着温暖的话语。只需20元,就能让这份美好的情感传递给那个特别的人。”

这与使用模型和带有{}占位符的提示语有什么区别?

只需要定义一次模板,就可以用它来生成各种不同的提示。更重要的是,使用LangChain提示模板,可以方便地把程序切换到不同的模型,而不需要修改与提示相关的代码。

输出解析

从模型输出中获取结构化的信息,加快基于语言模型进行应用开发的效率。

例如:在文案中,希望模型返回两个字段:

  • description:鲜花的说明文本
  • reason:解释一下为何要这样写上面的文案

模型返回的可能结果是:

但在处理数据时需要的是类似于下面的Python字典。

A笼统语言->B结构清晰的数据结构。

# 导入LangChain中的提示模板
from langchain_core.prompts import PromptTemplate
from langchain_community.llms import Tongyi
import os
# 导入结构化输出解析器和ResponseSchema
from langchain.output_parsers import StructuredOutputParser, ResponseSchema
import pandas as pd


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

# 创建模型实例
os.environ["DASHSCOPE_API_KEY"] ='阿里的DASHSCOPE_API_KEY'
llm = Tongyi(model_name="qwen-chat", api_key=os.environ["DASHSCOPE_API_KEY"])

# 定义我们想要接收的响应模式
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"]

df = pd.DataFrame(columns=["flower", "price", "description", "reason"]) # 先声明列名

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

    # 获取模型的输出
    output = llm.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)
[{'flower': '玫瑰', 'price': '50', 'description': '💖 每一朵都承载着爱与祝福,精选50元玫瑰,让您的情感更加浓烈。无论是浪漫的情人节,还是温馨的日常,这束玫瑰都是传递心意的最佳选择。立即选购,给Ta一个惊喜!', 'reason': '此文案通过强调玫瑰的情感价值和适用场合,吸引顾客关注。使用表情符号增加亲和力,同时突出价格优势,激发购买欲望。'}, {'flower': '百合', 'price': '30', 'description': '纯洁如雪,高雅脱俗。这束精选百合,以最自然的姿态绽放,传递着真挚的情感与美好的祝愿。30元,让这份纯净之美装点您的生活空间。', 'reason': '此文案突出了百合的纯洁和高雅特质,强调了其自然美和情感价值,同时明确了价格,使顾客感到物超所值,激发购买欲望。'}, {'flower': '康乃馨', 'price': '20', 'description': '每一朵康乃馨都承载着温馨与爱意,精致而优雅,是向母亲、长辈表达敬意和感激之情的最佳选择。在这个特别的日子里,让这份细腻的情感,以最真挚的方式传递出去。', 'reason': '这样的文案不仅突出了康乃馨本身所代表的美好寓意,还强调了它在特定场合下的情感价值,能够触动消费者内心深处的情感需求,激发购买欲望。同时,通过描述康乃馨的精致与优雅,也提升了产品的形象,使其在众多商品中脱颖而出。'}]

补充:

1.Prompt

input_variables=['flower_name', 'price'] input_types={} partial_variables={'format_instructions': 'The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":\n\n```json\n{\n\t"description": string  // 鲜花的描述文案\n\t"reason": string  // 问什么要这样写这个文案\n}\n```'} template='您是一位专业的鲜花店文案撰写员。\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n{format_instructions}'

2.吴恩达老师的提示工程课程 Multimodal RAG: Chat with Videos - DeepLearning.AI