langchain源码阅读系列(一)之LLM输入输出管理

news2024/11/18 13:35:27

原文首发于博客文章OpenAI 文档解读

LangChain 主体分为 6 个模块,分别是对(大语言)模型输入输出的管理、外部数据接入、链的概念、(上下文记忆)存储管理、智能代理以及回调系统,通过文档的组织结构,你可以清晰了解到 LangChain的侧重点,以及在大语言模型开发生态中对自己的定位。从本节开始我将对langchian各个模块对照源码进行介绍,首先看Model I/O模块👇

Model I/O

这部分包括对大语言模型输入输出的管理,输入环节的提示词管理(包含模板化提示词和提示词动态选择等),处理环节的语言模型(包括所有LLMs的通用接口,以及常用的LLMs工具;Chat模型是一种与LLMs不同的API,用来处理消息),输出环节包括从模型输出中提取信息。

提示词管理

  • 提示模板
    动态提示词=提示模板+变量,通过引入给提示词引入变量的方式,一方面保证了灵活性,一方面又能保证Prompt内容结构达到最佳

    from langchain import PromptTemplate
    no_input_prompt = PromptTemplate(input_variables=[], template="Tell me a joke.")
    no_input_prompt.format()
    
    one_input_prompt = PromptTemplate(input_variables=["adjective"], template="Tell me a {adjective} joke.")
    # "Tell me a funny chickens."
    one_input_prompt.format(adjective="funny")
    
    multiple_input_prompt = PromptTemplate(
        input_variables=["adjective", "content"], 
        template="Tell me a {adjective} joke about {content}."
    )
    # "Tell me a funny joke about chickens."
    multiple_input_prompt.format(adjective="funny", content="chickens")
    
  • 聊天提示模板
    聊天场景中,消息可以与AI、人类或系统角色相关联,模型应该更加密切地遵循系统聊天消息的指示。这个是对 OpenAI gpt-3.5-tubor API中role字段(role 的属性用于显式定义角色,其中 system 用于系统预设,比如”你是一个翻译家“,“你是一个写作助手”,user 表示用户的输入, assistant 表示模型的输出)的一种抽象,以便应用于其他大语言模型。SystemMessage对应系统预设,HumanMessage用户输入,AIMessage表示模型输出,使用 ChatMessagePromptTemplate 可以使用任意角色接收聊天消息。

    from langchain.prompts import (
        ChatPromptTemplate,
        PromptTemplate,
        SystemMessagePromptTemplate,
        AIMessagePromptTemplate,
        HumanMessagePromptTemplate,
    )
    from langchain.schema import (
        AIMessage,
        HumanMessage,
        SystemMessage
    )
    
    def generate_template():
        template="You are a helpful assistant that translates {input_language} to {output_language}."
        system_message_prompt = SystemMessagePromptTemplate.from_template(template)
        human_template="{text}"
        human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
        
        chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
        # [SystemMessage(content='You are a helpful assistant that translates English to Chinese.', additional_kwargs={}), HumanMessage(content='I like Large Language Model', additional_kwargs={}, example=False)]
        final_message = chat_prompt.format_prompt(input_language="English", output_language="Chinese", text="I like Large Language Model").to_messages()
        print(final_message)
    
    if __name__ == "__main__":
        generate_template()
    
  • 其他

    • 基于 StringPromptTemplate 自定义提示模板StringPromptTemplate
    • 将Prompt输入与特征存储关联起来(FeaturePromptTemplate)
    • 少样本提示模板(FewShotPromptTemplate)
    • 从示例中动态提取提示词

LLMs

  • LLMs

    将文本字符串作为输入并返回文本字符串的模型(纯文本补全模型),这里重点说下做项目尽量用异步的方式,体验会更好,下面的例子连续10个请求,时间相差接近5s。

    import time
    import asyncio
    from langchain.llms import OpenAI
    def generate_serially():
        llm = OpenAI(temperature=0.9)
        for _ in range(10):
            resp = llm.generate(["Hello, how are you?"])
            print(resp.generations[0][0].text)
    
    async def async_generate(llm):
        resp = await llm.agenerate(["Hello, how are you?"])
        print(resp.generations[0][0].text)
    
    async def generate_concurrently():
        llm = OpenAI(temperature=0.9)
        tasks = [async_generate(llm) for _ in range(10)]
        await asyncio.gather(*tasks)
    
    if __name__ == "__main__":
        s = time.perf_counter()
        asyncio.run(generate_concurrently())
        elapsed = time.perf_counter() - s
        print("\033[1m" + f"Concurrent executed in {elapsed:0.2f} seconds." + "\033[0m")
    
        s = time.perf_counter()
        generate_serially()
        elapsed = time.perf_counter() - s
        print("\033[1m" + f"Serial executed in {elapsed:0.2f} seconds." + "\033[0m")
    
  • 缓存

    如果多次请求的返回一样,就可以考虑使用缓存,一方面可以减少对API调用次数节省token消耗,一方面可以加快应用程序的速度。

    from langchain.cache import InMemoryCache
    import time
    import langchain
    from langchain.llms import OpenAI
    llm = OpenAI(model_name="text-davinci-002", n=2, best_of=2)
    langchain.llm_cache = InMemoryCache()
    s = time.perf_counter()
    llm("Tell me a joke")
    elapsed = time.perf_counter() - s
    # executed first in 2.18 seconds.
    print("\033[1m" + f"executed first in {elapsed:0.2f} seconds." + "\033[0m")
    llm("Tell me a joke")
    # executed second in 0.72 seconds.
    elapsed2 = time.perf_counter() - elapsed
    print("\033[1m" + f"executed second in {elapsed2:0.2f} seconds." + "\033[0m")
    
  • 流式传输

    以打字机效果的方式逐字返回聊天内容

    from langchain.llms import OpenAI
    from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
    llm = OpenAI(streaming=True, callbacks=[StreamingStdOutCallbackHandler()], temperature=0)
    resp = llm("模仿李白的风格写一首唐诗.")
    print(resp)
    
  • 跟踪 token 消耗情况
    流式传输的情况下暂不支持计算,可以考虑内容全部传输完成后用tiktoken库计算

    from langchain.llms import OpenAI
    from langchain.callbacks import get_openai_callback
    llm = OpenAI()
    with get_openai_callback() as cb:
        resp = llm.generate(["模仿李白的风格写一首唐诗."])
        print(resp.generations[0][0].text)
        print(cb)
    
  • Chat models
    将聊天消息列表作为输入并返回聊天消息的模型(对话补全模型)

  • 其他

    • 以json或者yml格式读取保存LLM的(参数)配置(llm.load_llm方法和llm.save方法)
    • 为了节省你的token,还可以在测试过程中使用一个模拟LLM输出的FakeListLLM;还有一个模拟用户输入的HumanInputLLM
    • 与其他 AI相关基础设施的集成,用到随时查询即可

输出解析器

输出解析器用于构造大语言模型的响应格式,具体通过格式化指令和自定义方法两种方式。

# 格式化指令的方式
from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
output_parser = CommaSeparatedListOutputParser()
format_instructions = output_parser.get_format_instructions()
prompt = PromptTemplate(
    template="列出五个 {subject}.\n{format_instructions}",
    input_variables=["subject"],
    partial_variables={"format_instructions": format_instructions}
)
model = OpenAI(temperature=0)
_input = prompt.format(subject="大语言模型的特性")
output = model(_input)
# 可移植性, 可扩展性, 可重用性, 可维护性, 可读性
print(output)
output_parser.parse(output)

虽然内置了 DatetimeOutputParser、EnumOutputParser、PydanticOutputParser等解析器,但是我觉得ResponseSchema的控制自由度更好,但是不易于管理。

from langchain.output_parsers import StructuredOutputParser, ResponseSchema
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
response_schemas = [
    ResponseSchema(name="answer", description="answer to the user's question"),
    ResponseSchema(name="source", description="source used to answer the user's question, should be a website.")
]
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
format_instructions = output_parser.get_format_instructions()
prompt = PromptTemplate(
    template="answer the users question as best as possible.\n{format_instructions}\n{question}",
    input_variables=["question"],
    partial_variables={"format_instructions": format_instructions}
)

资源推荐

  1. Guidance:微软开源 prompt 编程框架

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/681823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何编写一个最简单的 udp 版本的 echo server 和 echo client(小白也懂!)

目录 目的 第一步 编写Server(服务器) 第二步 创建Server的各类参数 第三步 实现具体的Server内容 第四步 编写Client(客户端) 实现具体的Client内容 总流程 总代码 源码下载 目的 我们编写一个udp 版本的 echo server 和 echo client 实现在自己电脑上通过客户端…

open【部署、使用教程】

目录 【1】创建证书 【2】安装openVPN-Server端并配置 【3】将证书移动到相对路径 【4】开启内核转发功能,否则会无法启动openVPN 【5】启动服务,加入开机自启 【6】启动后服务端会生成一个tun0的虚拟网卡,用于不同网段之间相互通信 【…

VUE2.0集成 Markdown 编辑器

Markdown编辑器的使用 这是一款基于Vue的markdown编辑器。既可以用来编辑Markdown语法,又可以用来解析 效果图,mavonEditor实现了Markdown集成 Markdown是一种标记语言,相较于word文档更加清晰方便,适合进行笔记等。将Markdown集成进入自己项…

Matlab使用S函数

什么是S函数? S-函数是系统函数(System Function)的简称,在 Simulink 中用非图形化的方式来描述一个模块。一个完整的S-函数结构体系包含了描述一个动态系统所需要的全部能力。使用S-函数用户可以向 Simulink 模型中添加自己的模块…

【PCB专题】Allegro中设置泪滴

PCB绘制完成后有时按需要对PCB进行添加泪滴的操作是非常必要的。 添加泪滴的作用主要是: 信号传输时平滑阻抗,减少阻抗的急剧跳变,避免高频信号传输时由于线宽突然变小而造成反射。 焊接时可以保护焊盘,避免多次焊接时焊盘的脱落,生产时可以避免蚀刻不均,以及过孔偏位出…

一键安装和导出当前Python项目的依赖包总结

创建python环境,配置一个python运行项目。在项目可以运行的环境下,导出该项目所依赖包到一个requirements.txt文档中。在另一个纯净环境中,快速批量安装项目所依赖的包,便于快速进行项目迁移 一、导出当前Python项目的依赖包1、方…

【数据结构与算法】3、虚拟头节点、动态数组的缩容、动态数组和单链表的复杂度、数组的随机访问

目录 一、虚拟头节点二、数组的随机访问三、动态数组、链表复杂度分析四、动态数组 add(E element) 复杂度分析五、动态数组的缩容 一、虚拟头节点 🌼 为了让代码更加精简,统一所有节点的处理逻辑,可以在最前面增加一个虚拟的头节点&#xf…

2023 年最佳 C++ IDE

文章目录 前言1. Visual Studio2. Code::Blocks3. CLion4. Eclipse CDT(C/C 开发工具)5. CodeLite6. Apache NetBeans7. Qt Creator8. Dev C9. C Builder10. Xcode11. GNAT Programming Studio12. Kite总结 前言 要跟踪极佳 IDE(集成开发环境…

嵌入式系统复习要点

目录 1、嵌入式系统的核心部分主要由硬件和软件两部分组成: 2、嵌入式系统硬件: 3、嵌入式处理器从体系上分类,可以分为冯诺依曼结构和哈佛结构两种: 4、几类常见的嵌入式处理器类型: 5、MCU组成结构:…

chatgpt赋能python:介绍:Python经典小游戏合集

介绍:Python经典小游戏合集 作为一门简洁易学、受到广泛喜爱的编程语言,Python已经在各个领域中得到了广泛应用,包括游戏开发。在这篇文章中,我们将为您介绍一些Python编程中的经典小游戏,让您感受到Python的多功能性…

idea乱码的相关问题

idea控制台乱码(即:tomacat等启动时的乱码) 第一步: 控制台tomcat启动信息乱码解决(红色字体) 1 在本地 tomcat 的配置文件中找到 logging.properties 文件设置日志输出的编码为 UTF-8 追加的配置信息为…

【Android复习笔记】Handler机制(一)

从 Android 初学者常见的一个错误开始: 导致这个错误的代码通常长下面这样: new Thread(){@Overridepublic void run() {new Handler(); } }.

chatgpt赋能python:Python编程中常见的问题和解决方案

Python编程中常见的问题和解决方案 Python作为一门高级编程语言,广泛用于数据分析、人工智能、Web开发等领域,然而在实际应用中我们不可避免地会遇到许多问题。在本文中,我们将探讨一些常见的Python编程问题以及解决方案。 1. 编码问题 Py…

碰撞检测算法详述

算法的分类 目录 一、基于空间域的碰撞检测算法分类 1. 基于图像空间的碰撞算法 2.基于几何空间的碰撞检测算法 (1)基于空间剖分算法 (2)裁剪扫掠法 (3)基于距离场的算法 (4)…

ModaHub魔搭社区:向量数据库的工作原理

目录 1. 为什么需要向量数据库 1)CPU 工作原理 2)GPU 工作原理 3)二者的差异 4)总结 5)大模型的工作原理 学习 推理 1. 为什么需要向量数据库 向量数据库这一概念随着黄仁勋的演讲火爆了之后,不少…

如何使用upupw搭建服务器,并映射外网访问

作为计算机行业从业人员,相信很多人都接触并使用过phpstudy等类似环境集成包,着对于upupw就比较好理解了。UPUPW绿色服务器平台是Windows下很有特色的一款免费服务器PHP套件,UPUPW PHP套件简化了PHP环境搭建步骤,一个压缩包解压到…

chatgpt赋能python:Python经典游戏:从命令行到桌面

Python经典游戏:从命令行到桌面 Python是一个热门的编程语言,尤其在编写游戏方面表现出色。Python允许开发人员使用简单的语法和丰富的库编写高效率的游戏。在这篇文章中,我们将介绍Python的一些经典游戏,包括简单的命令行游戏和…

GithubAction的使用-简单易懂

一、Github Action简介 github Action (工作流),简单理解就是自动化部署、测试。也就是之前人工手动部署变为现在由机器(服务器)自动部署、测试了。 二、对github Action(工作流)的使用 首先…

〖编程初学者的自我修养 - 满分面试篇①〗- 面试之前需要做的「长期准备工作」

简介:应 850 小伙伴要求, 无论你是迷茫的在校生还是已经就业的老司机,该专栏都值得你订阅,它会让你成就更好的自己!说明:该文属于 编程初学者的自我修养 专栏,购买任意白宝书体系化专栏可加入易…

SpringBoot 解决跨站脚本漏洞(XSS)问题

一、问题背景 使用 SpringBoot 的项目出现了跨站脚本漏洞&#xff08;XSS&#xff09;问题。 二、解决方案 步骤如下&#xff1a; 1、添加maven依赖 在 pom.xml 文件中&#xff0c;增加如下依赖&#xff1a; <dependency><groupId>org.apache.tomcat</group…