一、LangChain介绍
LangChain 是一个用于开发由语言模型驱动的应用程序的框架。它使得应用程序能够:
- 具有上下文感知能力:将语言模型连接到上下文来源(提示指令,少量的示例,需要回应的内容等)
- 具有推理能力:依赖语言模型进行推理(根据提供的上下文如何回答,采取什么行动等)
基本框架包含下面几个部分:
- LangChain 库:Python 和 JavaScript 库。包含了各种组件的接口和集成,一个基本的运行时,用于将这些组件组合成链和代理,以及现成的链和代理的实现。
- LangChain 模板:一系列易于部署的参考架构,用于各种任务。
- LangServe:一个用于将 LangChain 链部署为 REST API 的库。
- LangSmith:一个开发者平台,让你可以调试、测试、评估和监控基于任何 LLM 框架构建的链,并且与 LangChain 无缝集成。
这些产品一起简化了整个应用程序的生命周期:
- 开发:在 LangChain/LangChain.js 中编写你的应用程序。使用模板作为参考,快速开始。
- 生产化:使用 LangSmith 来检查、测试和监控你的链,这样你可以不断改进并有信心地部署。
- 部署:使用 LangServe 将任何链转换为 API。
二、快速入门
LangChain提供了许多可以用来构建语言模型应用程序的模块。这些模块可以作为简单应用程序中的独立模块使用,也可以组合在一起用于更复杂的用例。
LangChain应用程序的核心构建模块是LLMChain。它结合了三个方面:
- LLM: 语言模型是核心推理引擎。要使用LangChain,您需要了解不同类型的语言模型以及如何使用它们。
- Prompt Templates: 提供语言模型的指令。这控制了语言模型的输出,因此了解如何构建提示和不同的提示策略至关重要。
- Output Parsers: 将LLM的原始响应转换为更易处理的格式,使得在下游使用输出变得容易。
1. LLM
LangChain中有两种类型的语言模型,称为:
- LLMs: 这是一个以字符串作为输入并返回字符串的语言模型
- ChatModels: 这是一个以消息列表作为输入并返回消息的语言模型
1.1 LLMs
LLMs的输入/输出简单易懂, 就是字符串。我们首先看下如何使用LLMs这种语言模型。
下面的示例都是在uv的虚拟环境下运行。
-
环境安装
创建uv项目
uv init langchainlearning
创建虚拟环境
cd langchainlearning
uv venv
激活虚拟环境
.venv\Scripts\activate
安装相关依赖包
(langchainlearning) D:\learning\langchainlearning>uv add langchain
(langchainlearning) D:\learning\langchainlearning>uv add openai
(langchainlearning) D:\learning\langchainlearning>uv add langchain-openai
- 使用方式
在该虚拟环境下进入python命令行:
(langchainlearn) D:\learning\langchainlearn>python
Python 3.12.3 (tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
测试如下:
>>> from langchain_openai import OpenAI
>>> llm = OpenAI(
... base_url="xxxxx", # 你的大模型的url
... model="xxxxx", # 你的大模型名称
... api_key="xxxx" # 你的api-key
... )
>>> llm.invoke("你好,请介绍下你自己")
上面代码中先使用OpenAI创建一个llm变量,然后使用invoke调用,并传入一个字符串作为调用的参数。
1.2 ChatModels
- 传入一个字符串
>>> from langchain_openai import ChatOpenAI
>>> chat_model = ChatOpenAI(
... base_url="xxxxx", # 你的大模型的url
... model="xxxxx", # 你的大模型名称
... api_key="xxxx" # 你的api-key
... )
>>> chat_model.invoke("hello")
- 传入message
>>> from langchain.schema import HumanMessage
>>> text = "制造多彩袜子的公司的好名字是什么?"
>>> messages = [HumanMessage(content=text)]
>>> chat_model.invoke(messages)
输出信息:
AIMessage(content='\n以下是几个适合多彩袜子公司的创意命名方案,分为不同风格供参考:\n\n一、奇幻童话风\n1. 色predicted( 预测色彩)\n2. Chromosprout(色彩萌芽)\n3. Footopia Land(足尖乌托邦)\n4. LumaSole(光影足底)\n\n二、现代科技感\n5. Vivid kinetics(活力动力学)\n6. Chromaf Hazard(色彩 hazard)\n7. Euphoria Step(愉悦步程)\n8. Neon Thread(霓虹线)\n\n三、创意文化型\n9. sokkByNature(自带趣味)\n10. Polychromatic Pupilliseconds(多色永恒兔)——灵感源自希腊神话中的时间女神-moving\n11. Colorspire(色彩迸发)\n12. Tr illusionzés(多彩幻觉:gicznych为匈牙利语"幻觉")\n\n四、极简国际范\n13. Chromos\n14. Sprearty(spreading + party)\n15. VOOX(视觉+未来感)\n16. DECO Fallen(设计坠入)——暗合色彩坠落足尖的意境\n\n命名逻辑说明:\n1. 视觉联想:75%的名称内置颜色/光谱词汇(Chroma/Neon/Frequency)\n2. 感官延伸:42%名称包含足部体验暗示(footopia/sole/step)\n3. 文化融合:采用多语素组合,如匈牙利语+希腊神话元素\n4. 语音节奏:平均音节数4.2个,符合心理学最佳记忆长度\n5. 商标保护:特别设计的名称已通过全球商标数据库初筛(注:实际注册前需专业核查)\n\n推荐验证流程:\n1. 商标预查:建议优先注册简写形态如ChroSpre\n2. 域名矩阵:检查.com/.shop等主流后缀组合\n3. 语音测试:邀请母语者进行发音测试(如Sprearty易读性较高)\n4. 文化适配:重点核查在西班牙语系中是否存在负面含义\n\n备选技术增强点:\n- 可推出NFT数字袜样注册体系,名称关联区块链存证\n- 开发AR命名系统,扫描商标可查看动态袜子色彩演变\n- 包含色彩坐标系名称,如RGBTowym(RGB+Unicode)\n\n建议重点考虑的组合:\n1. ChromoSpre(Chroma+色系变化/Spre=spreading的谐音)\n2. LumaSole Pro(专业线光感足底)\n3. VOOX Color contemporaries(当代色彩先锋)\n\n这些名字具有:100%色彩关联、86%国际发音无障碍、78%agram商标通过率(经初步AI评估)\n\n需要进一步协助可提供:\n1. 目标国家/地区倾向\n2. 品牌技术特性(是否智能袜子等)\n3. 是否已有视觉识别元素需结合\n\n附:名称注册可行性分析表(15秒速查版):\n| 名称 | 全球注册量 | 风险等级 | 首选TLD |\n|---------------|------------|----------|----------|\n| Colorspire | 27 | 中 | .com |\n| Footopia | 8 | 低 | .xyz |\n| VOOX | 0 | 无 | .com |\n| Sprearty | 15 | 中 | .brand |\n| LumaSole | 9 | 低 | .red |\n\n建议 immediately(tomorrow) 注册decorative .travel域名保证商标安全\n\n(注:以上数据基于2023年8月实时查询,具体需以实际核查结果为准)', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 1189, 'prompt_tokens': 17, 'total_tokens': 1206, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 413, 'rejected_prediction_tokens': None}, 'prompt_tokens_details': None}, 'model_name': 'THUDM/GLM-Z1-9B-0414', 'system_fingerprint': '', 'id': '0196bd70277fe35320f43f133b264426', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--04abff1f-b502-414f-9f08-7ef19100103b-0', usage_metadata={'input_tokens': 17, 'output_tokens': 1189, 'total_tokens': 1206, 'input_token_details': {}, 'output_token_details': {'reasoning': 413}})
LangChain提供了几个对象,用于方便地区分不同的角色:
- HumanMessage: 来自人类/用户的ChatMessage。
- AIMessage: 来自AI/助手的ChatMessage。
- SystemMessage: 来自系统的ChatMessage。
- FunctionMessage: 来自函数调用的ChatMessage。
- ToolMessage: 工具调用的ChatMessage, 替代旧版FunctionMessage。
- ChatMessage: 自定义角色, 需要手动指定role的非标准消息(新版本才有)
另外新版本中,消息类从 langchain.schema 迁移到 langchain_core.messages。
2. 提示模板
大多数LLM应用程序不会直接将用户输入传递到LLM中。通常,它们会将用户输入添加到一个更大的文本片段中,称为提示模板,该模板提供了有关特定任务的附加上下文。
2.1 格式化字符串
可以先创建一个模板,再通过格式化创建不同的提示词。
>>> from langchain.prompts import PromptTemplate
>>> prompt = PromptTemplate.from_template("What is a good name for a company that makes {product}?")
>>> formatted_prompt = prompt.format(product="colorful socks")
>>> print(formatted_prompt)
输出:
What is a good name for a company that makes colorful socks?
可以一次只格式化某些变量。可以将它们组合在一起,轻松地将不同的模板组合成一个单独的提示。
2.2 格式化消息列表
PromptTemplates还可以用于生成消息列表。在这种情况下,提示不仅包含有关内容的信息,还包含每个消息(其角色、其在列表中的位置等) 在这里,最常见的是ChatPromptTemplate是ChatMessageTemplate的列表。每个ChatMessageTemplate包含了格式化该ChatMessage的指令 - 其角色,以及其内容。让我们在下面看一下这个:
>>> from langchain.prompts.chat import (
... ChatPromptTemplate,
... SystemMessagePromptTemplate,
... HumanMessagePromptTemplate
... )
>>> 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])
>>> chat_prompt.format_messages(input_language="English", output_language="French", text="I love programming.")
格式化后的模板提示信息为:
[SystemMessage(content='You are a helpful assistant that translates English to French.', additional_kwargs={}, response_metadata={}), HumanMessage(content='I love programming.', additional_kwargs={}, response_metadata={})]
>>>
3. 输出解释器
OutputParsers将LLM的原始输出转换为可以在下游使用的格式。输出解析器有几种主要类型,包括:
- 将LLM的文本转换为结构化信息(例如JSON)
- 将ChatMessage转换为字符串
- 将除消息之外的其他信息(如OpenAI函数调用)转换为字符串。
下面就是一个输出解释器的例子,把逗号分隔的列表转换为列表
>>> from langchain.schema import BaseOutputParser
>>> class CommaSeparatedListOutputParser(BaseOutputParser):
... """Parse the output of an LLM call to a comma-separated list."""
... def parse(self, text: str):
... """Parse the output of an LLM call."""
... return text.strip().split(", ")
...
>>> CommaSeparatedListOutputParser().parse("hi, bye")
输出如下:
['hi', 'bye']
4. LLMChain
现在,我们可以将所有这些组合成一个链组件。这个链组件将接收输入变量,将其传递给提示模板以创建提示,将提示传递给LLM,然后通过一个(可选的)输出解析器将输出传递出去。这是一种方便地将模块化逻辑捆绑在一起的方式。让我们看看它的作用!
>>> from langchain_openai import ChatOpenAI
>>> from langchain_core.prompts import (
... ChatPromptTemplate,
... SystemMessagePromptTemplate,
... HumanMessagePromptTemplate
... )
>>> from langchain_core.output_parsers import BaseOutputParser
# 1. 自定义输出解析器
>>> class CommaSeparatedListOutputParser(BaseOutputParser):
... def parse(self, text: str):
... return text.strip().split(", ")
...
# 2. 构建提示模板
>>> system_template = """You are a helpful assistant who generates comma separated lists.
... A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
... ONLY return a comma separated list, and nothing more."""
>>> system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
>>>
>>> human_template = "{text}"
>>> human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
>>>
>>> chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
# 3. 使用新版管道语法(旧版使用LLMChain,包含三个参数传递的方式)
>>> chain = (
... chat_prompt
... | ChatOpenAI(
... base_url="xxxxx", # 你的大模型的url
... model="xxxxx", # 你的大模型名称
... api_key="xxxx" # 你的api-key
... )
... | CommaSeparatedListOutputParser()
... )
>>>
# 4. 调用(使用新版的invoke替代旧版本的run)
>>> result = chain.invoke({"text": "colors"})
>>>
# 5. 打印执行结果
>>> print(result)
['red', 'blue', 'green', 'purple', 'orange']
>>>
我们初步构造了一个简单的LLMChain程序的演示,包含了最基本的三个组件(LLMs、prompts、输出解析器)的使用。当然,不仅这三个组件还有很多其他的使用方式,另外还有很多其他不同的组件需要了解。