AI测试 LangChain 0.3 一些组件的学习

唱跳rap打篮球 · 2025年08月13日 · 521 次阅读

大家好!我是新人唱跳 rap 打篮球,是一个立志 2025 年开始每周都能水一篇文章的人


之前一段时间学习机器学习相关的文档,分享了一个机器学习的基础例子,今天换个口味,学习一下 LangChain 一些组件

这里主要从其他地方拿来的代码,走读,按自己的理解简单分享一下

先决条件

python==3.9.23

requirements.txt

dotenv==0.9.9
langchain==0.3.27
langchain-community==0.3.27
langchain-core==0.3.72
langchain-openai==0.3.28
langsmith==0.4.10
openai==1.98.0
pyautogen==0.2.32
python-dotenv==1.1.1

通过.env 配置 base_url 和 api_key

有些依赖是其他代码会用,这里一起 copy 过来了

LLMChain 演示(使用 LCEL)

import os

from langchain_core.prompts import PromptTemplate
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

load_dotenv()
base_url = os.getenv('xiaoai')
api_key = os.getenv('xiaoai_api_key')
# ========== 1. 初始化 LLM(大语言模型) ==========
# LangChain 特点:统一的 LLM 接口,支持多种模型提供商
llm = ChatOpenAI(
    base_url=base_url,
    api_key=api_key,
    model="gpt-4o",
    temperature=0.7  # LangChain 特点:统一的参数配置
)


def demo_llm_chain():
    """
    演示 LLMChain:支持变量注入与模板复用的核心组件
    LangChain 特点:模板化提示词管理,支持变量替换
    """
    print("=" * 50)
    print("🔗 LLMChain 演示:Prompt → LLM → 输出链")
    print("=" * 50)

    # 创建提示词模板 - LangChain 特点:模板复用
    prompt_template = PromptTemplate(
        input_variables=["topic", "style"],
        template="""
        请以{style}的风格,写一段关于{topic}的介绍。
        要求:简洁明了,不超过100字。
        """
    )

    # LangChain 0.3 推荐使用 LCEL (LangChain Expression Language)
    # 这是新的链式组合方式:prompt | llm
    chain = prompt_template | llm

    # 执行链 - 变量注入
    result = chain.invoke({"topic": "人工智能", "style": "科普"})
    print(f"📝 LLMChain 输出:\n{result.content}\n")

    return result.content

if __name__ == '__main__':
    demo_llm_chain()

例子 1 是演示 LangChain 模板化提示词管理,支持变量替换的特点

  • 首先我们通过ChatOpenAI初始化 LLM 大语言模型

    • base_url 指定代理服务的 url 地址
    • api_key 指定代理服务创建的 api_key
    • model 指定要调用的模型
    • temperature 模型回答多样性参数,区间为 0~1,值越大多样性越大
  • 通过PromptTemplate创建提示词模板

    • PromptTemplate主要参数为input_variablestemplateinput_variables为 list 类型,指定 template 中使用{}包裹的变量的名
    • 通过PromptTemplate我们创建了一个基础的模板,以什么样的风格写一段什么样的介绍,并指定简介明了,不超过 100 字
  • 使用 LCEL(LangChain Expression language)方式,进行 langchain 方式的语言表达语法

    • chain = prompt_template | llm 让模板与之前声明的llm模型结合,形成一个链
    • 通过chain.invoke()并传入字典参数{"topic": "人工智能", "style": "科普"},实现对链的调用

Tools 演示

Tools:工具系统

from langchain_core.tools import Tool
import datetime


# ========== 3. Tools:工具系统 ==========
def get_current_time(query: str) -> str:
    """获取当前时间的工具函数"""
    return f"当前时间是:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"


def calculate_simple(expression: str) -> str:
    """简单计算器工具"""
    try:
        # 安全的数学表达式计算
        allowed_chars = set('0123456789+-*/.() ')
        if all(c in allowed_chars for c in expression):
            result = eval(expression)
            return f"计算结果:{expression} = {result}"
        else:
            return "错误:包含不允许的字符"
    except Exception as e:
        return f"计算错误:{str(e)}"


# LangChain 特点:统一的工具接口定义
tools = [
    Tool(
        name="get_time",
        func=get_current_time,
        description="获取当前的日期和时间信息"
    ),
    Tool(
        name="calculator",
        func=calculate_simple,
        description="执行简单的数学计算,如加减乘除运算"
    )
]


def demo_tools():
    """演示 Tools 工具系统"""
    print("=" * 50)
    print("🛠️ Tools 演示:工具系统")
    print("=" * 50)

    for tool in tools:
        print(f"工具名称:{tool.name}")
        print(f"工具描述:{tool.description}")

        # 测试工具
        if tool.name == "get_time":
            result = tool.run("现在几点了?")
        else:
            result = tool.run("10 + 5 * 2")

        print(f"工具输出:{result}\n")


if __name__ == '__main__':
    demo_tools()

例子 2 演示的是 LangChain 如何定义统一的工具,我们按照对应的接口定义即可自己编写自己想要的 tools

  • 我们创建了get_current_timecalculate_simple两个方法作为我们的工具函数

    • get_current_time用来获取当前时间
    • calculate_simple用来计算数学表达式
  • 通过Tool去定义统一的工具

    • Tool通过namefuncdescription参数初始化Tool工具类,name为工具名称,func为我们创建的函数,description为工具描述
  • 我们可以通过初始化的示例,调用run方法并传入参数并返回对应的工具调用结构

简化版 Agents 演示

例子 03 演示简化版的 Agents

import os
import datetime

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

# 加载环境变量
load_dotenv()
base_url = os.getenv('xiaoai')
api_key = os.getenv('xiaoai_api_key')
# ========== 1. 初始化 LLM(大语言模型) ==========
# LangChain 特点:统一的 LLM 接口,支持多种模型提供商
llm = ChatOpenAI(
    base_url=base_url,
    api_key=api_key,
    model="gpt-4o",
    temperature=0.7  # LangChain 特点:统一的参数配置
)


def get_current_time(query: str) -> str:
    """获取当前时间的工具函数"""
    return f"当前时间是:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"


def calculate_simple(expression: str) -> str:
    """简单计算器工具"""
    try:
        # 安全的数学表达式计算
        allowed_chars = set('0123456789+-*/.() ')
        if all(c in allowed_chars for c in expression):
            result = eval(expression)
            return f"计算结果:{expression} = {result}"
        else:
            return "错误:包含不允许的字符"
    except Exception as e:
        return f"计算错误:{str(e)}"


# ========== 4. 简化版 Agents:手动工具选择演示 ==========
def demo_simple_agents():
    """
    演示简化版 Agents:手动工具选择和执行
    LangChain 特点:工具集成和智能选择(这里用简化版演示概念)
    """
    print("=" * 50)
    print("🤖 简化版 Agents 演示:工具选择与执行")
    print("=" * 50)

    # 创建工具选择提示词
    tool_selection_prompt = ChatPromptTemplate.from_messages([
        ("system", """你是一个智能助手,可以使用以下工具:
        1. get_time - 获取当前时间
        2. calculator - 执行数学计算

        请分析用户问题,选择合适的工具并说明原因。
        只回答工具名称和原因,格式:工具名称|原因"""),
        ("human", "{question}")
    ])

    tool_chain = tool_selection_prompt | llm

    test_questions = [
        "现在几点了?",
        "帮我计算 15 * 8 + 20",
        "今天是什么日期?"
    ]

    for question in test_questions:
        print(f"👤 用户问题:{question}")

        # 1. 工具选择
        selection_result = tool_chain.invoke({"question": question})
        print(f"🧠 工具选择:{selection_result.content}")

        # 2. 执行工具(简化版手动执行)
        if "get_time" in selection_result.content.lower():
            result = get_current_time(question)
        elif "calculator" in selection_result.content.lower():
            # 提取数学表达式(简化处理)
            if "15 * 8 + 20" in question:
                result = calculate_simple("15 * 8 + 20")
            else:
                result = "需要具体的数学表达式"
        else:
            result = "未找到合适的工具"

        print(f"🛠️ 工具执行结果:{result}\n")


if __name__ == '__main__':
    demo_simple_agents()

例子 03 简化版 Agents 实现,但这里并没有直接让大模型调用函数,而是通过大模型的返回间接的调用了我们的工具函数

  • 首先还是通过 ChatOpenAI 初始化 llm 模型

  • 定义get_current_timecalculate_simple方法

  • 通过ChatPromptTemplate创建工具选择提示词

    • 它的参数是一个列表,里面设置了两个元组
      • 第一个元组第一个值为 system,第二个为具体的提示词
      • 第二个元组第一个值为 human,第二个使用{}包裹question字符,表示可替换的变量,表示会传入的提问
  • 使用 LCEL(LangChain Expression language)方式,进行 langchain 方式的语言表达语法

    • tool_chain = tool_selection_prompt | llm创建了一个链
  • 定义一个test_questions的列表,是我们提出的问题

  • 通过tool_chain.invoke({"question": question})来让大模型返回要调用的方法的字符

  • 通过我们代码去判断,手动代码选择要调用的方法并执行调用

可以看到这种 Agents 的实现还是有点弱智,但是确实实现了将自然语言转换为工具函数的调用并返回了结果。

Memory 演示

例子 04 演示 Memory 的使用,让大模型调用有记忆

import os

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

# 加载环境变量
load_dotenv()
base_url = os.getenv('xiaoai')
api_key = os.getenv('xiaoai_api_key')
# ========== 1. 初始化 LLM(大语言模型) ==========
# LangChain 特点:统一的 LLM 接口,支持多种模型提供商
llm = ChatOpenAI(
    base_url=base_url,
    api_key=api_key,
    model="gpt-4o",
    temperature=0.7  # LangChain 特点:统一的参数配置
)


# ========== 5. Memory:记忆系统 ==========
def demo_memory():
    """
    演示 Memory:对话记忆管理
    LangChain 特点:自动管理对话历史
    """
    print("=" * 50)
    print("🧠 Memory 演示:记忆系统")
    print("=" * 50)

    # 使用简化的记忆管理方式
    conversation_history = []

    # 创建带记忆的对话提示词
    memory_prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一个友好的助手,能够记住之前的对话内容。以下是对话历史:{history}"),
        ("human", "{input}")
    ])

    memory_chain = memory_prompt | llm

    # 模拟多轮对话
    conversations = [
        "我叫张三,今年25岁",
        "我喜欢编程和阅读",
        "你还记得我的名字吗?",
        "我的爱好是什么?"
    ]

    for i, user_input in enumerate(conversations, 1):
        print(f"👤 第{i}轮对话:{user_input}")

        # 构建历史记录字符串
        history_str = "\n".join([f"用户: {h['user']}\n助手: {h['assistant']}" for h in conversation_history])

        # 获取回复
        response = memory_chain.invoke({
            "history": history_str,
            "input": user_input
        })

        print(f"🤖 助手回复:{response.content}\n")

        # 更新对话历史
        conversation_history.append({
            "user": user_input,
            "assistant": response.content
        })

        # 显示当前记忆内容
        print(f"💭 当前记忆:{len(conversation_history)} 轮对话")
        print("-" * 30)


if __name__ == '__main__':
    demo_memory()

  • 首先初始化模型llm,这里不多介绍了

    • demo_memory方法来实现简单的记忆功能
    • conversation_history来简化记忆管理方式
  • 使用ChatPromptTemplate.from_messages来创建带记忆的对话提示词

    • 我们可以通过第一个元组的第二个值,传入history,来让system获取到之前的对话历史
    • 我们可以通过第二个元组的第二个值,传入input,来让human来进行提问
  • 通过history_str = "\n".join([f"用户: {h['user']}\n助手: {h['assistant']}" for h in conversation_history]),构建历史记录字符串

  • 调用memory_chain.invoke函数,传入 history 和 input 参数,获取到最新的回复

  • 通过conversation_history.append更新对话历史

通过以上的示例,我们实现了一个简单的记忆功能,通过conversation_history来保存对话历史,并通过history_str来构建历史记录字符串,并通过memory_chain.invoke函数来获取最新的回复。

LCEL 演示

例子 05 演示 LCEL(LangChain Expression Language)的使用

import os

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate

# 加载环境变量
load_dotenv()
base_url = os.getenv('xiaoai')
api_key = os.getenv('xiaoai_api_key')
# ========== 1. 初始化 LLM(大语言模型) ==========
# LangChain 特点:统一的 LLM 接口,支持多种模型提供商
llm = ChatOpenAI(
    base_url=base_url,
    api_key=api_key,
    model="gpt-4o",
    temperature=0.7  # LangChain 特点:统一的参数配置
)


# ========== 6. LCEL 演示:LangChain Expression Language ==========
def demo_lcel():
    """
    演示 LCEL:LangChain 0.3 的新特性
    LangChain 特点:更简洁的链式组合语法
    """
    print("=" * 50)
    print("🔗 LCEL 演示:LangChain Expression Language")
    print("=" * 50)

    # LCEL 语法:使用 | 操作符组合组件
    prompt = PromptTemplate.from_template("请用{language}语言解释什么是{concept}")

    # 创建链:prompt | llm
    chain = prompt | llm

    # 执行链
    result = chain.invoke({
        "language": "简单易懂的中文",
        "concept": "区块链"
    })

    print(f"📝 LCEL 链式调用结果:\n{result.content}\n")

    # 演示更复杂的链组合
    from langchain_core.output_parsers import StrOutputParser

    # 创建输出解析器
    output_parser = StrOutputParser()

    # 更复杂的链:prompt | llm | output_parser
    complex_chain = prompt | llm | output_parser

    result2 = complex_chain.invoke({
        "language": "技术术语",
        "concept": "机器学习"
    })

    print(f"📝 复杂 LCEL 链结果:\n{result2}\n")


if __name__ == '__main__':
    demo_lcel()

  • demo_lcel方法实现了简单的 lcel 和更复杂的链组合
  • 这里主要是创建了输出解析器
    • output_parser = StrOutputParser()
    • 然后定义了更复杂的链组合complex_chain = prompt | llm | output_parser
    • 通过complex_chain.invoke调用,获取到更复杂的链结果
    • 我们可以看到返回的结果是有结构的

特点总结

通过上面的例子,我们可以知道 LangChain 的一些特点,希望对你学习 LangChain 有一定帮助

当然, LangChain 还提供了很多的功能,比如:

"🔗 链式组合:使用 LCEL (|) 将多个组件串联",
"📝 模板管理:统一的提示词模板系统",
"🛠️ 工具集成:标准化的工具接口",
"🤖 智能代理:自动选择和使用工具(需模型支持)",
"🧠 记忆管理:灵活的对话历史管理",
"🔄 流程编排:灵活的工作流定义",
"📊 可观测性:详细的执行日志",
"🔌 模块化:组件可插拔设计",
"⚡ LCEL:简洁的表达式语言",
"🎯 类型安全:完整的类型提示支持"

如果感兴趣可以去官网自己再学习更多的内容

听说 LangGraph 现在也是很火,有机会也分享一下

今天就水到这里了,晚安!


我是新人唱跳 rap 打篮球,是一个立志 2025 年开始每周都能水一篇文章的人,希望我的文章可以给你带来好心情!

暫無回覆。
需要 登录 後方可回應,如果你還沒有帳號按這裡 注册