LangChain

163 阅读5分钟

LangChain

一、环境配置

pip install --upgrade langchain
pip install --upgrade langchain-openai
pip install --upgrade langchain-community

二、实例代码

0)环境变量
OPENAI_API_KEY=xxx
OPENAI_BASE_URL=https://xxx/v1
1)OpenAI模型封装
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

load_dotenv()

# 保证操作系统的环境变量里面配置好了OPENAI_API_KEY, OPENAI_BASE_URL
llm = ChatOpenAI(model="gpt-4o-mini")  # 默认是gpt-3.5-turbo
response = llm.invoke("你是谁")
print(response.content)

2)多轮对话Session封装
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

load_dotenv()

llm = ChatOpenAI(model="gpt-4o-mini")
from langchain.schema import (
    AIMessage,  # 等价于OpenAI接口中的assistant role
    HumanMessage,  # 等价于OpenAI接口中的user role
    SystemMessage  # 等价于OpenAI接口中的system role
)

messages = [
    SystemMessage(content="你是一个聪明的的学习助手。"),
    HumanMessage(content="我是你的主人,我叫小李。"),
    AIMessage(content="欢迎!"),
    HumanMessage(content="我是谁")
]
# 把消息格式转换为openai的格式,然后调用chat/completion接口
ret = llm.invoke(messages)

print(ret.content)

3)propmt模板封装
from dotenv import load_dotenv

load_dotenv()


def t0():
    """
    PromptTemplate 可以在模板中自定义变量
    :return:
    """
    from langchain.prompts import PromptTemplate

    template = PromptTemplate.from_template("给我讲个关于{subject}的笑话")
    print("===Template===")
    print(template)
    print("===Prompt===")
    print(template.format(subject='小明'))

    from langchain_openai import ChatOpenAI

    # 定义 LLM
    llm = ChatOpenAI(model="gpt-4o-mini")
    # 通过 Prompt 调用 LLM
    ret = llm.invoke(template.format(subject='小明'))
    # 打印输出
    print(ret.content)


def t1():
    """
    ChatPromptTemplate 用模板表示的对话上下文
    :return:
    """
    from langchain.prompts import (
        ChatPromptTemplate,
        HumanMessagePromptTemplate,
        SystemMessagePromptTemplate,
    )
    from langchain_openai import ChatOpenAI

    template = ChatPromptTemplate.from_messages(
        [
            SystemMessagePromptTemplate.from_template("你是{product}的客服助手。你的名字叫{name}"),
            HumanMessagePromptTemplate.from_template("{query}"),
        ]
    )

    llm = ChatOpenAI(model="gpt-4o-mini")
    prompt = template.format_messages(
        product="小李",
        name="小小李",
        query="你是谁"
    )

    print(prompt)

    ret = llm.invoke(prompt)
    print("------------------------------")
    print(ret.content)


def t2():
    """
    MessagesPlaceholder 把多轮对话变成模板
    :return:
    """
    from langchain.prompts import (
        ChatPromptTemplate,
        HumanMessagePromptTemplate,
        MessagesPlaceholder,
    )

    # 人类模板
    human_prompt = "Translate your answer to {language}."
    human_message_template = HumanMessagePromptTemplate.from_template(human_prompt)

    # 聊天模板
    chat_prompt = ChatPromptTemplate.from_messages(
        # variable_name 是 message placeholder 在模板中的变量名
        # 用于在赋值时使用
        [MessagesPlaceholder("history"), human_message_template]
    )

    from langchain_core.messages import AIMessage, HumanMessage

    # 人类消息
    human_message = HumanMessage(content="Who is Elon Musk?")

    # ai消息
    ai_message = AIMessage(
        content="Elon Musk is a billionaire entrepreneur, inventor, and industrial designer"
    )

    # 对聊天模型进行填充值
    messages = chat_prompt.format_prompt(
        # 对 "history" 和 "language" 赋值
        history=[human_message, ai_message], language="中文"
    )

    print(messages.to_messages())

    from langchain_openai import ChatOpenAI

    llm = ChatOpenAI(model="gpt-4o-mini")
    result = llm.invoke(messages)
    print(result.content)


if __name__ == '__main__':
    # t0()
    # t1()
    t2()

4)从文件加载Prompt模板
举一个关于{topic}的例子
def t0():
    from langchain.prompts import PromptTemplate

    template = PromptTemplate.from_file("example_prompt_template.txt", encoding="utf-8")
    print("===Template===")
    print(template)
    print("===Prompt===")
    prompt = template.format(topic='如何学习AI')

    print(type(prompt))
    print(prompt)


if __name__ == '__main__':
    t0()

5)结构化输出
from dotenv import load_dotenv

load_dotenv()


def t_my_test():
    from pydantic import BaseModel, Field

    class Date(BaseModel):
        year: int = Field(description="Year")
        month: int = Field(description="Month")
        day: int = Field(description="Day")
        era: str = Field(description="BC or AD")

    d = Date(year=2020, month=3, day=4, era="BC")
    print(type(d))
    print(d)


def t0():
    """
    直接输出 Pydantic 对象
    底层走的就是function call。把自定义类当成函数了,直接调用然后返回结果。eg:Date(year=2020, month=3, day=4, era="BC")
    :return:
    """
    from pydantic import BaseModel, Field

    # 定义你的输出对象
    class Date(BaseModel):
        year: int = Field(description="Year")
        month: int = Field(description="Month")
        day: int = Field(description="Day")
        era: str = Field(description="BC or AD")

    from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
    from langchain_openai import ChatOpenAI

    from langchain_core.output_parsers import PydanticOutputParser

    model_name = 'gpt-4o-mini'
    temperature = 0
    llm = ChatOpenAI(model_name=model_name, temperature=temperature)

    # 定义结构化输出的模型
    structured_llm = llm.with_structured_output(Date)

    template = """提取用户输入中的日期。
    用户输入:
    {query}"""

    prompt = PromptTemplate(
        template=template,
    )

    query = "2024年十二月23日天气晴..."
    input_prompt = prompt.format_prompt(query=query)
    # D:\Env\Anaconda3\envs\langchain-learn\Lib\site-packages\openai\resources\chat\completions.py

    res = structured_llm.invoke(input_prompt)
    print(res)


def t1():
    """
    输出指定格式的 JSON,
    底层走的function call
    :return:
    """
    json_schema = {
        "title": "Date",
        "description": "Formated date expression",
        "type": "object",
        "properties": {
            "year": {
                "type": "integer",
                "description": "year, YYYY",
            },
            "month": {
                "type": "integer",
                "description": "month, MM",
            },
            "day": {
                "type": "integer",
                "description": "day, DD",
            },
            "era": {
                "type": "string",
                "description": "BC or AD",
            },
        },
    }

    from langchain_openai import ChatOpenAI
    model_name = 'gpt-4o-mini'
    temperature = 0
    llm = ChatOpenAI(model_name=model_name, temperature=temperature)

    # 绑定结构化输出
    structured_llm = llm.with_structured_output(json_schema)

    template = """提取用户输入中的日期。
    用户输入:
    {query}"""

    from langchain.prompts import PromptTemplate
    prompt = PromptTemplate(
        template=template,
    )

    query = "2024年十二月23日天气晴..."
    input_prompt = prompt.format_prompt(query=query)

    res = structured_llm.invoke(input_prompt)
    print(res)


def t2():
    """
    使用OutputParser,可以按指定格式解析模型的输出

    核心是通过构建提示词,来让模型结构化输出,然后通过解析器进行解析
    :return:
    """

    from pydantic import BaseModel, Field
    from langchain.prompts import PromptTemplate
    from langchain_openai import ChatOpenAI

    # 定义你的输出对象
    class Date(BaseModel):
        year: int = Field(description="Year")
        month: int = Field(description="Month")
        day: int = Field(description="Day")
        era: str = Field(description="BC or AD")

    from langchain_core.output_parsers import JsonOutputParser

    parser = JsonOutputParser(pydantic_object=Date)

    prompt = PromptTemplate(
        template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
        input_variables=["query"],
        partial_variables={"format_instructions": parser.get_format_instructions()},
    )
    print(f"prompt:{prompt}")

    query = "2024年十二月23日天气晴..."
    input_prompt = prompt.format_prompt(query=query)
    print(f"input_prompt:{input_prompt}")  # 通过构建提示词,来让模型结构化输出

    model_name = 'gpt-4o-mini'
    temperature = 0
    llm = ChatOpenAI(model_name=model_name, temperature=temperature)
    output = llm.invoke(input_prompt)
    print("原始输出:\n" + output.content)

    print("\n解析后:")
    res = parser.invoke(output)
    print(res)


def t3():
    """
    使用PydanticOutputParser,可以按指定格式解析模型的输出
    核心是通过构建提示词,来让模型结构化输出,然后通过解析器进行解析
    :return:
    """
    from pydantic import BaseModel, Field
    from langchain.prompts import PromptTemplate
    from langchain_openai import ChatOpenAI

    # 定义你的输出对象
    class Date(BaseModel):
        year: int = Field(description="Year")
        month: int = Field(description="Month")
        day: int = Field(description="Day")
        era: str = Field(description="BC or AD")

    from langchain_core.output_parsers import PydanticOutputParser

    parser = PydanticOutputParser(pydantic_object=Date)

    prompt = PromptTemplate(
        template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
        input_variables=["query"],
        partial_variables={"format_instructions": parser.get_format_instructions()},
    )
    print(f"prompt:{prompt}")

    query = "2024年十二月23日天气晴..."
    input_prompt = prompt.format_prompt(query=query)
    print(f"input_prompt:{input_prompt}")

    model_name = 'gpt-4o-mini'
    temperature = 0
    llm = ChatOpenAI(model_name=model_name, temperature=temperature)
    output = llm.invoke(input_prompt)
    print("原始输出:\n" + output.content)

    print("\n解析后:")
    res = parser.invoke(output)
    print(res)


def t4():
    """
    `OutputFixingParser` 利用大模型做格式自动纠错
    :return:
    """

    from pydantic import BaseModel, Field
    from langchain.prompts import PromptTemplate
    from langchain_openai import ChatOpenAI

    # 定义你的输出对象
    class Date(BaseModel):
        year: int = Field(description="Year")
        month: int = Field(description="Month")
        day: int = Field(description="Day")
        era: str = Field(description="BC or AD")

    from langchain_core.output_parsers import PydanticOutputParser

    parser = PydanticOutputParser(pydantic_object=Date)

    prompt = PromptTemplate(
        template="提取用户输入中的日期。\n用户输入:{query}\n{format_instructions}",
        input_variables=["query"],
        partial_variables={"format_instructions": parser.get_format_instructions()},
    )
    print(f"prompt:{prompt}")

    query = "2024年十二月23日天气晴..."
    input_prompt = prompt.format_prompt(query=query)
    print(f"input_prompt:{input_prompt}")

    model_name = 'gpt-4o-mini'
    temperature = 0
    llm = ChatOpenAI(model_name=model_name, temperature=temperature)
    output = llm.invoke(input_prompt)
    print("原始输出:\n" + output.content)

    print("\n解析后:")
    res = parser.invoke(output)
    print(res)

    # -------------------------
    from langchain.output_parsers import OutputFixingParser

    new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI(model="gpt-4o"))

    bad_output = output.content.replace("4", "四")
    print("bad_output为:\n" + bad_output)
    print("PydanticOutputParser:")
    try:
        res = parser.invoke(bad_output)
        print(res)
    except Exception as e:
        print(e)

    print("OutputFixingParser:")
    res = new_parser.invoke(bad_output)  # 底层通过提示词让模型进行纠错返回。
    print(res)


if __name__ == '__main__':
    # t_my_test()
    # t0()
    # t1()
    # t3()
    t4()