LangChain中的模型 I/O| 豆包MarsCode AI刷题

181 阅读12分钟

一, LangChain中的模型 I/O

LangChain 中模型 I/O 的三个关键环节:输入提示(Prompt Engineering)调用模型输出解析(Output Parsing) ,并利用它们构建了一个自动生成鲜花文案的应用程序。

核心知识点与收获:

1. 输入提示:Prompt Template

  • 意义

    • 提示是模型生成内容的基础。好的提示设计(Prompt Engineering)决定了生成内容的质量。
    • LangChain 提供了模板功能,使提示的生成更加清晰和模块化。
  • 实现方法

    • 使用 PromptTemplate 创建动态提示模板。
    • 示例中通过占位符 {flower_name}{price},灵活地将不同变量替换到提示中,形成特定输入。

2. 调用模型

  • 模型类型

    • 大语言模型(LLM):处理输入和输出为字符串。
    • 聊天模型(Chat Model):处理对话内容。
    • 文本嵌入模型(Embedding Model):生成向量表示。
  • LangChain 的优点

    • 统一接口:通过 LangChain,切换不同的模型变得简单,无需更改代码结构。
    • 灵活性:模板与模型解耦,适配多种语言模型(如 OpenAI 的 GPT 系列和 HuggingFace 的开源模型)。
  • 实现步骤

    • 创建模型实例(如 OpenAI 或 HuggingFaceHub 模型)。
    • 调用模型接口(例如 invoke 方法)生成内容。

3. 输出解析:Output Parser

  • 意义

    • 生成结果是文本时,可能需要提取有用信息。
    • 输出解析器可以将非结构化文本转换为结构化数据,方便后续处理(如存入数据库或导出为 CSV)。
  • 实现方法

    • 定义结构化输出(ResponseSchema)。
    • 使用 StructuredOutputParser 提取模型输出。
    • 结合 pandas 将解析的结果组织成表格,并保存到文件中。
  • 优势

    • 清晰的结构化数据:方便程序理解与进一步处理。
    • 灵活性:轻松应对多字段、多格式需求。

使用 LangChain 的整体优势:

  1. 模块化设计:将提示、模型调用、输出解析分离,代码更易读、易维护。
  2. 复用性强:一次性定义的模板或解析器可以应用于不同任务。
  3. 可扩展性:支持切换不同模型和 API,无需修改提示模板或解析逻辑。
  4. 简化开发:即使面对复杂的模型交互,LangChain 也能高效管理 I/O 流程。

二, 应用的创造性:

  • 通过 LangChain 的框架,我们开发的应用不仅仅执行预设逻辑,还能展现大语言模型的生成能力,具有强大的创造性
  • 不同于传统编程,每次运行生成的结果可能不同,为业务开发注入更多灵感和变数。

如果你的重点是要更深入了解为什么 partial_variables 和输出解析器的 format_instructions 能引导模型生成结构化输出,我们可以从以下几个层面分析:

1. partial_variables 的作用

partial_variables 是在构建提示模板时用来预填充某些变量的机制。在实际操作中,它可以帮助我们动态构造提示的一部分,同时将其他部分的变量留待进一步格式化。例如:

partial_template = PromptTemplate(
    input_variables=["occasion"],
    template="鲜花类型: 玫瑰\n场合: {occasion}\n文案: {ad_copy}",
    partial_variables={"ad_copy": "玫瑰代表爱情,传递真挚情感。"}
)

这种机制可以将部分变量锁定,从而避免重复填充,并确保提示中每个组件都符合预期的结构。通过预定义格式,它为模型提供了更加一致的上下文。


2. 输出解析器与 format_instructions 的作用

输出解析器(Output Parser)与 format_instructions 的核心任务,是 向模型明确地指示输出的格式,这通常通过以下步骤完成:

  • 嵌入格式指令format_instructions 提供了一种结构化的模板,例如 JSON、Markdown 等,告诉模型其输出应以特定的模式出现。
  • 降低自由度:通过明确指令限制模型的输出格式,减少不必要的生成变体。

例如,下面是一段带有格式指令的提示:

template = """
你是一位专业的鲜花店文案撰写员。
对于售价为 {price} 元的 {flower} ,你能提供一个吸引人的简短描述吗?

The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":

```json
{
    "description": string, // 鲜花的描述文案
    "reason": string       // 为什么要这样写这个文案
}

"""

**这一段中的 `format_instructions` 的作用** 是告诉模型“要以 JSON 的形式回复”,并将变量占位符嵌入格式中,确保生成的输出能被程序进一步解析。

---

### 3. **为什么格式指令能有效?**
格式指令能够有效,是因为:
- **大模型在训练时接触过类似的结构化任务**:模型会优先遵循明确的格式要求,因为它“知道”这样能满足用户需求。
- **语境提示的作用**:格式指令为模型提供了强烈的语境信号(contextual cue),它倾向于模仿指令中描述的输出形式。
- **减少生成中的自由发挥**:没有指令时,模型的生成可能是任意形式,而明确的 `format_instructions` 会强制其按需生成。

例如,在有 `format_instructions` 的情况下,模型知道:
1. 输出需要以 JSON 开头和结束。
2. 键值对必须按照模板出现。
3. 内容是严格规定的。

---

### 4. **完整的 `print` 打印展示作用**
打印提示时,可以观察到 `format_instructions` 的内容如何嵌入到整体提示中。这使得提示的生成过程变得透明化,同时帮助验证提示是否合规。例如,最终的提示可能如下:

你是一位专业的鲜花店文案撰写员。 对于售价为 50 元的玫瑰,您能提供一个吸引人的简短描述吗?

The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "json" and "":

{
    "description": string, // 鲜花的描述文案
    "reason": string       // 为什么要这样写这个文案
}
这时,模型的输出可能严格遵循此格式:

```json
{
    "description": "玫瑰,传递浪漫情感的最佳选择,让爱意自然绽放。",
    "reason": "玫瑰象征浪漫,使用简洁且富有情感的语言能更打动消费者。"
}

5. 总结:结构化输出的关键

  • 清晰的任务指令:通过 partial_variablesformat_instructions,明确告诉模型其角色、任务和输出形式。
  • 丰富的语境和示例:结合 Few-Shot 示例,可以进一步强化模型对任务的理解。
  • 提示透明化:通过 print 检查提示,确保其包含所有必要信息,并在逻辑上清晰无误。

这些技巧共同作用,确保模型生成的是 结构化且可预测的输出

三,关于 Chain of Thought (CoT) 和 Tree of Thoughts (ToT) 实战练习

任务 1: 将 Few-Shot CoT 替换为 Zero-Shot CoT 并运行程序

思路

  • Few-Shot CoT 的核心是通过示例展示中间推理步骤,从而指导模型解题。
  • Zero-Shot CoT 的核心则是直接告诉模型按步骤思考,而无需提供示例。

Zero-Shot CoT 示例代码替换:

在程序的 cot_template 部分,可以替换为以下内容:

cot_template = """
作为一个为花店电商公司工作的AI助手,我的目标是帮助客户根据他们的喜好做出明智的决定。

我会按部就班地思考:首先理解客户的需求,然后考虑各种鲜花的涵义,最后根据需求给出我的推荐。
同时,我也会向客户解释推荐理由。

请一步一步地解释你的思考过程并提供最终建议。
"""

在这种情况下,模型将没有明确的 Few-Shot 示例,而是依据“按步骤思考”的指导逻辑来进行解答。

运行程序后,你可以观察模型生成的回答,比较其与 Few-Shot CoT 的效果差异。一般来说,Zero-Shot CoT 能更清晰地展示模型的推理能力,但在特定任务中可能不如 Few-Shot CoT 稳定。


任务 2: 用 ToT 解决工作场景中的任务需求

示例场景:假设你的工作是运营一个在线教育平台,需要制定一份年度用户增长策略。

我们通过 ToT 框架引导模型完成以下任务:

  • 确定目标。
  • 分解增长策略。
  • 探索不同方法的优劣。
  • 综合分析并提出可行方案。

以下是 ToT 框架提示的具体设计:

tot_template = """
你是一位在线教育平台的战略顾问,目标是帮助我们设计年度用户增长策略。

你的任务是一步一步地思考,构建一个清晰的思维树:
1. 首先理解我们的目标(例如:用户增长、留存率提升等)。
2. 分解增长策略可能的关键领域(如营销、内容质量、用户体验等)。
3. 针对每个关键领域,提出至少3种可行方案。
4. 分析每种方案的优劣,解释它们对用户增长的影响。
5. 综合考虑这些方法,建议一个最终的年度用户增长策略。

请按部就班地详细展开你的思考。
"""

运行代码: 将上述 tot_template 替换到程序中,然后输入以下问题:

human_input = "我们希望在2024年提升平台用户数量,目标是全年增长50%。你能帮助设计增长策略吗?"

模型将根据 ToT 提供详细的用户增长建议,包括方法和分析。


总结

  • Zero-Shot CoT 替换:简化了模板,直接要求模型“按步骤思考”。
  • ToT 实战设计:通过分步引导模型进行多路径分析,适合复杂任务如年度增长策略。

四,大模型的训练与使用流程

  1. 预训练:在大规模无标注数据上进行训练,学习通用语言表示基础。
  2. 微调:在领域或任务特定的小规模标注数据集上进一步训练,使模型适配特定需求。
  3. 量化:优化模型大小与性能(如GGML或GPTQ格式),降低硬件需求。
  4. 推理与应用:在生产环境中加载模型并部署到系统,完成具体任务。

核心工具与框架

  1. HuggingFace

    • 提供便捷访问海量开源模型的接口。
    • 支持从预训练到微调的完整流程。
  2. LangChain

    • 用于构建复杂的提示模板链,集成开源与自定义模型。
    • 与HuggingFace等模型接口无缝对接。
  3. llama-cpp-python

    • 专为本地运行量化模型设计,可在CPU和GPU环境下高效推理。

实践中的关键步骤

1. HuggingFace调用模型

  • 直接使用预训练模型(如Meta的Llama 2系列)。
  • 在本地加载、定义推理Pipeline后,结合LangChain实现任务链。

2. LangChain整合开源模型

  • 提供简单方法调用HuggingFace Hub模型或本地Pipeline。
  • 支持扩展到自定义微调模型,且接口标准化,易用性强。

3. 自定义本地模型

  • 使用量化模型(如Llama 2的GGML格式)在低成本设备上完成推理。
  • 构建自定义LLM类(如继承LangChain的LLM基类),适配个性化模型需求。

实际效果与挑战

  • 能力

    • 开源模型的表现逐渐逼近闭源系统(如GPT系列)。
    • 英文能力突出,中文处理仍有优化空间(量化后尤其明显)。
  • 效率

    • Llama 2的7B量化模型在本地CPU上运行具有可接受的性能。
    • 高效的模型部署与推理无需高端硬件支持。
  • 局限

    • 微调或定制模型的复杂性较高,对初学者不够友好。
    • 特定场景(如非英文领域)可能需要进一步优化。

五,Pydantic(JSON)解析器

Pydantic(JSON)解析器的核心作用是根据你预定义的Pydantic模型来验证和解析模型输出的数据结构。这意味着,你可以通过定义一个Pydantic类来强制输出符合预期的数据格式,并通过自动验证来避免不符合要求的数据。

关键步骤:

  1. 创建模型实例: 通过环境变量配置OpenAI API密钥,然后创建一个OpenAI模型实例。
  2. 定义数据结构: 使用Pydantic库定义期望的数据格式,例如FlowerDescription类,它描述了鲜花的类型、价格、描述和理由。
  3. 创建输出解析器: 使用PydanticOutputParser来创建输出解析器,该解析器确保模型输出符合预定的Pydantic模型结构。
  4. 生成提示模板: 将输出格式说明(JSON Schema)包含在提示中,确保模型能够生成符合要求的输出。
  5. 解析和存储数据: 在得到模型的输出后,通过解析器将其转换为Pydantic实例,最终存储在一个DataFrame中,方便进一步处理或存储为CSV文件。

自动修复解析器(OutputFixingParser)

自动修复解析器用于处理和修复模型的输出错误。例如,在某些情况下,模型生成的JSON格式可能不符合规范,如使用单引号代替双引号,或者缺少必要的字段。这时,OutputFixingParser可以介入,自动修复这些错误。

错误处理示例:

假设我们让模型生成鲜花的描述,但它返回了格式错误的JSON:

misformatted = "{'name': '康乃馨', 'colors': ['粉红色','白色','红色','紫色','黄色']}"

这个JSON使用了单引号代替双引号,Pydantic的解析器会抛出错误:Expecting property name enclosed in double quotes,此时就可以通过OutputFixingParser来修复这个错误,使其符合正确的JSON格式。