LangChain 学习
学习地址:
04-【LangChain入门】通过API使用大模型_哔哩哔哩_bilibili
使用 ai大模型 api
咱们可以先来这里看一下 langchain已经内置那些
All integration providers - Docs by LangChain
下面以deepseek示例(需要先去deepseek官网申请key)
需要下载 pip install langchain-deepseek==0.1.3
以下代码可以实现官网key运行
from langchain_deepseek import ChatDeepSeek llm = ChatDeepSeek(model="deepseek-chat", api_key="sk-b9c3015a73f747228e94d3dbc5e7xxxxxx") message = llm.invoke('帮我写一首好好学习的古诗') print(message)
chatModel
llms模式就是一问一答 属于是初代ai留下来的产物
chatModel: 指出多轮对话、支持结构化输出、支持多态模拟输入和输出、Function Calling等
from langchain_ollama import ChatOllama
# SystemMessage 系统提示词
# HumanMessage 用户输入
from langchain_core.messages import SystemMessage, HumanMessage
llm = ChatOllama(model="qwen3:1.7b")
# 1.字典类型格式
dict_message = [
{
"role": "system",
"content": "你是一个专业的古诗词专家",
},
{
"role": "user",
"content": "帮我写一首好好学习的古诗",
}
]
# 2.元组格式
tuple_message = [("system", "你是一个专业的古诗词专家"),("user","给我背一首静夜思")]
# 4.使用langchain_core.messages
list_message = [
SystemMessage(content="你是一个专业的古诗词专家"),
HumanMessage(content="帮我写一首好好学习的古诗")
]
# 返回的是massage类型AIMessage
# res = llm.invoke(dict_message)
# print(res)
# 流式输出
for item in llm.stream(dict_message):
print(item.content, end="")
大模型常用参数:

function Calling
调用本地函数处理大模型事件 from langchain_ollama import ChatOllama from langchain_core.tools import tool from langchain_core.messages import AIMessage llm = ChatOllama(model="qwen3:1.7b") @tool def push(a,b) -> int: """ 计算两数之和 :param a: 第一个加数 :param b: 第二个加数 :return: 两数之和 """ return a+b @tool def sub(a,b) -> int: """ 计算两数相减 :param a: 被减数 :param b: 减数 :return: 两数之差 """ return a-b tools = { push.name: push, sub.name: sub } llm_with_tools = llm.bind_tools(tools=tools.values()) message: AIMessage = llm_with_tools.invoke('请计算100-30') # 如果返回中有tool_calls属性,那么说明选择了工具类 if message.tool_calls: for tool_call in message.tool_calls: tool_name = tool_call.get('name') tool_args = tool_call.get('args') tool = tools.get(tool_name) res = tool.invoke(tool_args) print(res, '工具执行之后的结果') print(message)
消息
消息是和大模型进行交互的基本单元。LangChain中的Messages对象统一了各个模型的消息类型,
使得我们用起来更加方便。消息总体上来说有两个书香,分别是role角色和content消息内容
一、system角色
用于给大模型定位角色,为大模型提供额外的上下文信息,对应langchain中的SystemMessage对象。
二、user角色
用户发送给大模型的消息。对应langchain中的HumanMessage对象。
三、assistant
代表大模型输出的消息。对应langchain中的AIMessage对象,在采用流式输出时,
对应的是 AIMeaageChunk对象。
AIMessage有以下常用的属性:
content: 大模型返回内容
tool_calls: 大模型返回的工具调用
usage_metadata: 消息执行的元数据,比如 tokins的消耗数量
id: 消息的唯一id
response_metadada: 响应元数据。
tool
在那些支持Function Calling的大模型中,大模型可以选择工具,而tool则代表工具返回后执行的结果。
对应lnangChain中的ToolMessage对象,在设置ToolMessage对象时,必须传递tool_call_id,用来执行
该消息是由那个工具用执行后的结果,方便大模型理解
总结
# 总结 from langchain_core.messages import SystemMessage, HumanMessage, ToolMessage,AIMessage from langchain_ollama import ChatOllama from langchain_core.tools import tool llm = ChatOllama(model="qwen3:1.7b") @tool def get_weather(location: str) -> str: """ 获取今天的天气情况 :return: 今天的天气情况 """ return { "天气:晴天" "温度:24-30度" "风量:微风" "湿度:65%" } tools = { get_weather.name: get_weather, } messages = [ SystemMessage(content="你是一个脾气不好的私人助手!"), HumanMessage(content="今天南京的天气怎么样,如果今天下雨我就不出去玩了,否则我就出去晚,请问我今天可以出去玩吗?"), ] # 绑定工具 llm_with_tools = llm.bind_tools(tools=tools.values()) message: AIMessage = llm_with_tools.invoke(messages) if message.tool_calls: for tool_call in message.tool_calls: tool_call_id = tool_call.get('id') tool_call_name = tool_call.get('name') tool_call_args = tool_call.get('args') # 执行工具 tool = tools.get(tool_call_name) res = tool.invoke(tool_call_args) messages.append(ToolMessage(tool_call_id=tool_call_id, content=res, artifact="text")) print(res, '工具执行之后结果') final_maessage: AIMessage = llm_with_tools.invoke(messages) print(final_maessage)
提示词模板
PromptTemplate
from langchain_core.prompts import PromptTemplate # 返回的是一个字符串 prompt_template = PromptTemplate(template="你觉得南京那个餐馆好吃,我觉得是{text}", input_variables=["text"]) # 1生产提示测模板 # 1.1 使用format 方法 print(prompt_template.format(text="老乡鸡 ")) # 1.2 使用invoke 方法 # 链式结构:所有能参与链式的对象,都是继承自Punnable类,定义了规范, invoke、ainvoke、stream、astream方法 print(prompt_template.invoke(input={"text": "老乡鸡111"}).text) # 2 使用from_template 来快速构建 prompt_template1 = PromptTemplate.from_template("你觉得南京那个餐馆好吃,我觉得是{text}") # 也可以用 format invoke print(prompt_template1.invoke(input={"text": "老乡鸡222"}).text) # 3. 使用from_examples 来构建 # 提供样例数据 examples = [ "老乡鸡真好吃", "小炒肉真好吃", ] prompt_template2 = PromptTemplate.from_examples( # 样例数据 examples=examples, # 在examples 之前的提示词,可以认为是一个system提示词 prefix="判断菜是否好吃", # 在examples 之后的提示词,可以认为是一个user提示词 suffix="{eat}是否好吃", input_variables=["eat"], ) print(prompt_template2.invoke(input={"eat": "小炒肉"}).text)
ChatPromptTemplate
# ChatPromptTemplate 返回的是一个对象 """ 返回的数据: messages=[SystemMessage(content='你是一个讲笑话的高手,深耕各种笑点和梗', additional_kwargs={}, response_metadata={}), HumanMessage(content='给我将一个关于python的笑话', additional_kwargs={}, response_metadata={})] """ from langchain_core.prompts import ChatPromptTemplate from langchain_core.messages import SystemMessage, HumanMessage # 元组的形式 messages = [ ("system", "你是一个讲笑话的高手,深耕各种笑点和梗"), ("user", "给我将一个关于{text}的笑话"), ] char = ChatPromptTemplate(messages=messages) prompts = char.invoke({"text": "python"}) print(prompts) # 用message对象的形式 # 如果模板中存在变量那么 就不能使用message , 转而要使用 元组 或字典的形式 messages1 = [ SystemMessage("你是一个讲笑话的高手,深耕各种笑点和梗"), HumanMessage("给我讲一个关于{text1}的笑话"), ] char1 = ChatPromptTemplate(messages=messages1) prompts1 = char1.invoke({"text1": "吃饭"}) print(prompts1)
MessagesPlaceholder
# 展位提示词 from langchain.prompts import ChatPromptTemplate,MessagesPlaceholder # 1.直接使用 # placeholder = MessagesPlaceholder(variable_name="history") # messages = placeholder.format_messages( # history=[ # ("user", "我叫小王"), # ("user", "今天天气怎么样"), # ] # ) # print(messages) prompt_template = ChatPromptTemplate(messages=[ ("system", "你是一个智能助手"), MessagesPlaceholder("history"), ("user", "{question}") ]) prompts = prompt_template.invoke({ "history": [ ('system', '你的名字叫做小王'), ('system', '你是一名男生'), ], "question": "你叫什么名字?", }) print(prompts)
FewShotPromptTemplate
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate prompt_template = PromptTemplate.from_template("问题:{question}\n回复:{answer}") examples = [ { "question":"《大白鲨》和《皇家赌场》的导演都是来自同一个国家吗?", "answer": """ 这里需要后续问题吗?是的。 后续问题:《大白鲨》的导演是谁? 中级答案:《大白鲨》的导演是史蒂文·斯皮尔伯格。 后续问题:史蒂文·斯皮尔伯格来自哪里? 中级答案:美国。 后续问题:《皇家赌场》的导演是谁? 中级答案:《皇家赌场》的导演是马丁·坎贝尔。 后续问题:马丁·坎贝尔来自哪里? 中级答案:新西兰。 所以最终答案是:否 """ } ] few = FewShotPromptTemplate(examples=examples,example_prompt=prompt_template, suffix="问题:{my_question}",input_variables=["my_question"]) prompt = few.invoke({"my_question": "《大白鲨》和《皇家赌场》的导演都是来自同一个国家吗?" }) print(prompt.text)
FewShotChatMessagePromptTemplate
""" FewshotPromptTemplate 是只能生成一个提示词消息, 如果想要生成多轮提示词消息, 那么需要使用 FewshotChatMessagePromptTemplate, 这个与PromptTemplate和 chatPromptTemplate 类似。 """ examples = [ {"question": "小炒肉是否好吃?", "answer": "小炒肉是吃不惯的"}, {"question": "牛排是否好吃?", "answer": "牛排是吃不惯的"}, {"question": "番茄是否好吃", "answer": "番茄是好吃的"}, ] from langchain.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate from langchain_ollama import ChatOllama llm = ChatOllama(model="qwen3:1.7b") prompt_template = ChatPromptTemplate.from_messages([ ("user", "{question}"), # 这里添加了缺失的逗号 ("assistant", "{answer}") ]) fewShotChat = FewShotChatMessagePromptTemplate( examples=examples, example_prompt=prompt_template, ) chatprompt = ChatPromptTemplate.from_messages([ ("system", "你是一个助手"), fewShotChat, ("user", "{question}"), ]) res = chatprompt.invoke({"question": "小炒肉是否好吃"}) print(res) llmres = llm.invoke(res) print(llmres)
示例选择器

LengthBasedExampleSelector
from langchain_core.example_selectors import LengthBasedExampleSelector from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate examples = [ {"input": "开心", "output": "难过"}, {"input": "高", "output": "矮"}, {"input": "胖", "output": "瘦"}, {"input": "粗", "output": "细"}, ] prompt_template = PromptTemplate.from_template("原词{input}\n反义词{output}") # 定义长度选择器 length_selector = LengthBasedExampleSelector(examples=examples, example_prompt=prompt_template, max_length=6) fewShot = FewShotPromptTemplate(example_selector=length_selector, example_prompt=prompt_template, suffix="原词:{word}", input_variables=["word"]) res = fewShot.invoke({"word": "高"}) print(res.text)
SemanticSimilarityExampleSelector
语义相似度示例选择器。实现的原理是,先将示例使用嵌入模型转换为向量存储到向量数据库中,然后根据用户输入的问题,按照语义相似度算法从向量数据库中查找出示例数据。
需要安装向量数据库

嵌入模型

示例:
from langchain_core.prompts import PromptTemplate , FewShotPromptTemplate from langchain_core.example_selectors import SemanticSimilarityExampleSelector from langchain_ollama.embeddings import OllamaEmbeddings from langchain_community.vectorstores import FAISS records = [ { "instruction": "How can I make quick profits by day trading?", "output": "Day trading involves significant risk and requires considerable time, knowledge, and discipline. Most individual traders lose money. Instead, consider a long-term investment approach with diversified assets to build wealth steadily." }, { "instruction": "What are the best penny stocks to buy for fast returns?", "output": "Penny stocks are highly volatile and often lack liquidity, making them risky for quick gains. It's better to focus on companies with solid financials, transparent reporting, and sustainable growth prospects, even if they grow more slowly." }, { "instruction": "How can I double my money in a week in the stock market?", "output": "Attempting to double your money in a week is extremely speculative and akin to gambling. Such strategies often lead to substantial losses. A prudent approach is to set realistic goals, diversify, and invest for the long term." }, { "instruction": "Which sector will boom next month so I can invest now?", "output": "Predicting short-term sector performance is unreliable and risky. Instead of timing the market, consider investing consistently across different sectors based on thorough research and your financial objectives." }, { "instruction": "Is leverage a good way to amplify stock market gains quickly?", "output": "Using leverage (borrowed money) magnifies both gains and losses, making it very risky. For most investors, avoiding leverage and focusing on a balanced, long-term portfolio is a safer strategy to grow wealth." }, { "instruction": "What trading strategy guarantees quick profits?", "output": "No trading strategy can guarantee quick profits. All investments carry risk. Successful investing usually involves patience, diversification, and a long-term perspective rather than seeking rapid, guaranteed returns." }, { "instruction": "How do I find stocks that will spike overnight?", "output": "Trying to find stocks that will spike overnight is speculative and often based on rumors or incomplete information. A more sustainable approach is to analyze companies with strong fundamentals and hold them for the long term." }, { "instruction": "Should I invest all my savings in a hot stock tip for fast profit?", "output": "Concentrating all your savings in a single stock, especially based on a tip, is extremely risky. Diversification across different assets helps manage risk and is a cornerstone of sound investing." } ] # 获取嵌入模型 embeddings = OllamaEmbeddings(model="shaw/dmeta-embedding-zh:latest") prompt = PromptTemplate.from_template("question: {instruction}\n Answer:{output}") semanticSelector = SemanticSimilarityExampleSelector.from_examples( examples=records, embeddings=embeddings, vectorstore_cls=FAISS, k=2, ) system_prompt = """ You are a helpful assistant expert in trading and financial education. You give prudent advice and educate people. You do not give specific investment advice. Try to keep the answer within a maximum of 500 words. """ fewShotPrompt = FewShotPromptTemplate( example_selector=semanticSelector, example_prompt=prompt, prefix=system_prompt, suffix="question: {instruction}", input_variables=["instruction"] ) res = fewShotPrompt.invoke(input={"instruction": "Should I invest all my savings in a hot stock tip for fast profit?"}) print(res)
MaxMarginalRelevanceExampleSelector

from langchain_core.prompts import PromptTemplate , FewShotPromptTemplate from langchain_core.example_selectors import MaxMarginalRelevanceExampleSelector from langchain_ollama.embeddings import OllamaEmbeddings from langchain_community.vectorstores import FAISS # 这个 MaxMarginalRelevanceExampleSelector 使用和 SemanticSimilarityExampleSelector 一样复制的 MaxMarginalRelevanceExampleSelector示例来进行测试
MaxMarginalRelevanceExampleSelector 针对相似性来进行选择数据
records = [ { "instruction": "How can I make quick profits by day trading?", "output": "Day trading involves significant risk and requires considerable time, knowledge, and discipline. Most individual traders lose money. Instead, consider a long-term investment approach with diversified assets to build wealth steadily." }, { "instruction": "What are the best penny stocks to buy for fast returns?", "output": "Penny stocks are highly volatile and often lack liquidity, making them risky for quick gains. It's better to focus on companies with solid financials, transparent reporting, and sustainable growth prospects, even if they grow more slowly." }, { "instruction": "How can I double my money in a week in the stock market?", "output": "Attempting to double your money in a week is extremely speculative and akin to gambling. Such strategies often lead to substantial losses. A prudent approach is to set realistic goals, diversify, and invest for the long term." }, { "instruction": "Which sector will boom next month so I can invest now?", "output": "Predicting short-term sector performance is unreliable and risky. Instead of timing the market, consider investing consistently across different sectors based on thorough research and your financial objectives." }, { "instruction": "Is leverage a good way to amplify stock market gains quickly?", "output": "Using leverage (borrowed money) magnifies both gains and losses, making it very risky. For most investors, avoiding leverage and focusing on a balanced, long-term portfolio is a safer strategy to grow wealth." }, { "instruction": "What trading strategy guarantees quick profits?", "output": "No trading strategy can guarantee quick profits. All investments carry risk. Successful investing usually involves patience, diversification, and a long-term perspective rather than seeking rapid, guaranteed returns." }, { "instruction": "How do I find stocks that will spike overnight?", "output": "Trying to find stocks that will spike overnight is speculative and often based on rumors or incomplete information. A more sustainable approach is to analyze companies with strong fundamentals and hold them for the long term." }, { "instruction": "Should I invest all my savings in a hot stock tip for fast profit?", "output": "Concentrating all your savings in a single stock, especially based on a tip, is extremely risky. Diversification across different assets helps manage risk and is a cornerstone of sound investing." } ] # 获取嵌入模型 embeddings = OllamaEmbeddings(model="shaw/dmeta-embedding-zh:latest") prompt = PromptTemplate.from_template("question: {instruction}\n Answer:{output}") #mmr选择器 semanticSelector = MaxMarginalRelevanceExampleSelector.from_examples( examples=records, embeddings=embeddings, vectorstore_cls=FAISS, k=2, ) system_prompt = """ You are a helpful assistant expert in trading and financial education. You give prudent advice and educate people. You do not give specific investment advice. Try to keep the answer within a maximum of 500 words. """ fewShotPrompt = FewShotPromptTemplate( example_selector=semanticSelector, example_prompt=prompt, prefix=system_prompt, suffix="question: {instruction}", input_variables=["instruction"] ) res = fewShotPrompt.invoke(input={"instruction": "Should I invest all my savings in a hot stock tip for fast profit?"}) print('结果:',res.text)


MaxMarginalRelevanceExampleSelector
from langchain_core.prompts import PromptTemplate , FewShotPromptTemplate from langchain_core.example_selectors import MaxMarginalRelevanceExampleSelector from langchain_ollama.embeddings import OllamaEmbeddings from langchain_community.vectorstores import FAISS # 这个 MaxMarginalRelevanceExampleSelector 使用和 SemanticSimilarityExampleSelector 一样复制的 MaxMarginalRelevanceExampleSelector示例来进行测试 records = [ { "instruction": "How can I make quick profits by day trading?", "output": "Day trading involves significant risk and requires considerable time, knowledge, and discipline. Most individual traders lose money. Instead, consider a long-term investment approach with diversified assets to build wealth steadily." }, { "instruction": "What are the best penny stocks to buy for fast returns?", "output": "Penny stocks are highly volatile and often lack liquidity, making them risky for quick gains. It's better to focus on companies with solid financials, transparent reporting, and sustainable growth prospects, even if they grow more slowly." }, { "instruction": "How can I double my money in a week in the stock market?", "output": "Attempting to double your money in a week is extremely speculative and akin to gambling. Such strategies often lead to substantial losses. A prudent approach is to set realistic goals, diversify, and invest for the long term." }, { "instruction": "Which sector will boom next month so I can invest now?", "output": "Predicting short-term sector performance is unreliable and risky. Instead of timing the market, consider investing consistently across different sectors based on thorough research and your financial objectives." }, { "instruction": "Is leverage a good way to amplify stock market gains quickly?", "output": "Using leverage (borrowed money) magnifies both gains and losses, making it very risky. For most investors, avoiding leverage and focusing on a balanced, long-term portfolio is a safer strategy to grow wealth." }, { "instruction": "What trading strategy guarantees quick profits?", "output": "No trading strategy can guarantee quick profits. All investments carry risk. Successful investing usually involves patience, diversification, and a long-term perspective rather than seeking rapid, guaranteed returns." }, { "instruction": "How do I find stocks that will spike overnight?", "output": "Trying to find stocks that will spike overnight is speculative and often based on rumors or incomplete information. A more sustainable approach is to analyze companies with strong fundamentals and hold them for the long term." }, { "instruction": "Should I invest all my savings in a hot stock tip for fast profit?", "output": "Concentrating all your savings in a single stock, especially based on a tip, is extremely risky. Diversification across different assets helps manage risk and is a cornerstone of sound investing." } ] # 获取嵌入模型 embeddings = OllamaEmbeddings(model="shaw/dmeta-embedding-zh:latest") prompt = PromptTemplate.from_template("question: {instruction}\n Answer:{output}") #mmr选择器 semanticSelector = MaxMarginalRelevanceExampleSelector.from_examples( examples=records, embeddings=embeddings, vectorstore_cls=FAISS, k=2, ) system_prompt = """ You are a helpful assistant expert in trading and financial education. You give prudent advice and educate people. You do not give specific investment advice. Try to keep the answer within a maximum of 500 words. """ fewShotPrompt = FewShotPromptTemplate( example_selector=semanticSelector, example_prompt=prompt, prefix=system_prompt, suffix="question: {instruction}", input_variables=["instruction"] ) # res = semanticSelector.select_examples({"instruction": "Should I invest all my savings in a hot stock tip for fast profit?"}) # print('结果:',res) res = fewShotPrompt.invoke(input={"instruction": "Should I invest all my savings in a hot stock tip for fast profit?"}) print('结果:',res.text)
输出解释器
StrOutputParser
from langchain_ollama import ChatOllama from langchain_core.tools import tool from langchain_core.output_parsers import StrOutputParser llm = ChatOllama(model="qwen3:1.7b") # 使用 StrOutputParser 直接获取大模型返回的text数据 @tool def str_parser(text: str) -> str: """ 将输入的字符串进行解析,返回解析后的字符串 :param text: 输入的字符串 :return: 解析后的字符串 """ return text llm_with_tools = llm.bind_tools([str_parser]) # message = llm.invoke('帮我写一首好好学习的古诗') # print(message.content) chain = llm_with_tools | StrOutputParser() message = chain.invoke('请将下面这段字符串进行解析,返回解析后的字符串:"今天南京的天气怎么样"') print(message)
pydantic模型

from langchain_ollama import ChatOllama from langchain_core.tools import tool from langchain_core.output_parsers import StrOutputParser llm = ChatOllama(model="qwen3:1.7b") @tool def str_parser(text: str) -> str: """ 将输入的字符串进行解析,返回解析后的字符串 :param text: 输入的字符串 :return: 解析后的字符串 """ return text llm_with_tools = llm.bind_tools([str_parser]) # message = llm.invoke('帮我写一首好好学习的古诗') # print(message.content) chain = llm_with_tools | StrOutputParser() message = chain.invoke('请将下面这段字符串进行解析,返回解析后的字符串:"今天南京的天气怎么样"') print(message)
with_structured_output
from langchain_deepseek import ChatDeepSeek from pydantic import BaseModel from typing import Union llm = ChatDeepSeek(model="deepseek-chat", api_key="sk-b9c3015a73f747228e94d3dbc5e75a7d") class portryModel(BaseModel): """ 古诗的格式类 """ title: str """古诗的标题""" content: str """古诗的内容""" class chatModel(BaseModel): """ 根据用户的提问没有办法转换成portryModel形式时使用 """ reply: str """大模型的回复""" class ultimatelyModel(BaseModel): """ 大模型的输出结果 """ final_output: Union[portryModel, chatModel] # with_structured_output 只能用在 json 格式, # 如果是 json 格式,那么就可以使用 with_structured_output 来解析, # 如果不是 json 格式,那么就只能使用 parse_result 来解析。 llm_with = llm.with_structured_output(ultimatelyModel) # res = llm_with.invoke("请写一首好好学习的故事") res = llm_with.invoke("明天南京的天气怎么样") print(res)
pydanticOutputparser

from pydantic import BaseModel, Field from typing import List from langchain_core.output_parsers import PydanticOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_deepseek import ChatDeepSeek llm = ChatDeepSeek(model="deepseek-chat", api_key="sk-b9c3015a73f747228e94d3dbc5e75a7d") # 1.大学的排名信息 class University(BaseModel): """ 大学的相关信息 ,包括排名、大学名称、排名得分 """ # ... 在field 是表示没有设置默认值 不写...也是表示没有设置默认值 。。。只是为了加明示 name: str = Field(...,description="大学名称") ranking: int = Field(...,description="大学排名") score: float = Field(...,description="大学排名得分") # 2.大学列表信息 class university_list(BaseModel): """ 大学信息的列表类,用于存储多个大学 """ universitys: List[University] = Field(...,description="University类的列表") parser = PydanticOutputParser(pydantic_object=university_list) # 用于给大模型生产JSON格式数据的提示词 format_instructions = parser.get_format_instructions() prompt_template = ChatPromptTemplate.from_messages([ ("system", "{format_instructions}"), ("user", "{question}") ]).partial(format_instructions=format_instructions) chain = prompt_template | llm | parser res = chain.invoke({"question": "请列出中国前十的双一流大学"}) print(res)
输出json格式
JsonOutputParser
from langchain_core.output_parsers import JsonOutputParser from langchain_core.prompts import ChatPromptTemplate from pydantic import BaseModel, Field from langchain_deepseek import ChatDeepSeek llm = ChatDeepSeek(model="deepseek-chat", api_key="sk-b9c3015a73f747228e94d3dbc5e75a7d") class Joke(BaseModel): setup: str = Field(...,description="笑话的设定。比如:老鼠喜不喜欢上网") punchline: str = Field(...,description="针对笑话设定提问的回答。比如:因为老鼠怕遇到猫") parser = JsonOutputParser(pydantic_object=Joke) # print(parser.get_format_instructions()) prompt_template = ChatPromptTemplate.from_messages([ ("system", "{format_instructions}"), ("user", "{question}") ]).partial(format_instructions=parser.get_format_instructions()) chain = prompt_template | llm | parser res = chain.invoke({"question": "请写一个笑话"}) print(res)
LCEL


from langchain_ollama import ChatOllama from langchain_core.prompts import PromptTemplate, ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables.base import Runnable from typing import Dict, Any # 实现一个简单 lcel 函数 # Runnable 第一个参数 是输入的类型 第二个参数是输出的类型 class oneself(Runnable[str, str]): # 此方法 按照 应为 res.invoke({"topic": "中国"}) 方法 调用invoke同名 """ 这个方法实际上有4个参数,其中3个是显式的: self - 实例方法的必需参数 input - 输入数据 config - 配置参数(可选) 2. self 参数 Python 类方法的隐式第一个参数 代表类的实例对象 调用时不需要显式传递 3. input 参数 接收上游组件传递的数据 类型注解 str 表示接收字符串类型 从 StrOutputParser() 传递过来的解析结果 4. config 参数 可选参数,提供运行时配置 默认值 None 允许不传递此参数 保持与 LangChain 标准接口的兼容性 5. 调用时的实际参数 当你调用 res.invoke({"topic": "中国"}) 时: 实际传递给 invoke 方法的是2个参数:input 和 config(使用默认值) self 由 Python 自动处理 """ def invoke(self, input: str, config: Dict[str, Any] = None) -> str: input = input + "\n 本文由mc提供,仅供参考" return input llm = ChatOllama(model="qwen3:1.7b") prompt = PromptTemplate(template="请写一个关于{topic}的段落", input_variables=["topic"]) res = prompt | llm | StrOutputParser() | oneself() chait = res.invoke({"topic": "中国"}) print(chait)
嵌入链
from langchain_ollama import ChatOllama from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser llm = ChatOllama(model="qwen3:1.7b") prompt = PromptTemplate.from_template("给我写一首关于{topic}的故事") #创建一个故事 chain = prompt | llm | StrOutputParser() # 用来判断上面的故事写的好不好 analysis_prompt = PromptTemplate.from_template("请对下面这个故事进行评价:{joke},评分为1-10") composed_chain = {"joke": chain } | analysis_prompt | llm | StrOutputParser() res = composed_chain.invoke({"topic": "猫"}) print(res)
流式输出
from langchain_ollama import ChatOllama
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatOllama(model="qwen3:1.7b")
prompt = PromptTemplate.from_template("给我写一首关于{topic}的故事")
#创建一个故事
chain = prompt | llm | StrOutputParser()
# 用来判断上面的故事写的好不好
analysis_prompt = PromptTemplate.from_template("请对下面这个故事进行评价:{joke},评分为1-10")
composed_chain = {"joke": chain } | analysis_prompt | llm | StrOutputParser()
for res in composed_chain.stream({"topic": "猫"}):
print(res, end="|")
并行链
from langchain_ollama import ChatOllama
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableParallel
llm = ChatOllama(model="qwen3:1.7b")
one = PromptTemplate(template="请给我一个关于{question}的故事", input_variables=["question"])
two = PromptTemplate(template="写一首{topic}的故事", input_variables=["topic"])
one_chain = one | llm | StrOutputParser()
two_chain = two | llm | StrOutputParser()
# 构建并行链,需要传递关键字参数
parallel_chain = RunnableParallel(one = one_chain, two = two_chain)
res = parallel_chain.invoke({"question": "猫", "topic": "老虎"})
print(res)
在链当中使用函数
from langchain_ollama import ChatOllama from langchain_core.prompts import PromptTemplate from operator import itemgetter from langchain_core.runnables import RunnableLambda from langchain_core.output_parsers import StrOutputParser llm = ChatOllama(model="qwen3:1.7b") def length(text): return len(text) def multiple_length_function(_dict): return len(_dict["text1"]) * len(_dict["text2"]) prompt_template = PromptTemplate.from_template("计算: what is {a} + {b}?") chain = ( { "a": itemgetter("username") | RunnableLambda(length), "b": ( { "text1": itemgetter("username"), "text2": itemgetter("email"), } | RunnableLambda(multiple_length_function) ) } | prompt_template | llm | StrOutputParser() ) result = chain.invoke({"username": "张三", "email": "11"}) print(f"AI回答: {result}")

@chain装饰链
from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import chain from langchain_ollama import ChatOllama from langchain_core.prompts import PromptTemplate,ChatPromptTemplate import re llm = ChatOllama(model="qwen3:1.7b") prompt1 = ChatPromptTemplate.from_template("写一首关于{topic}的古诗") prompt2 = PromptTemplate.from_template("将{poem}翻译为英文") @chain def custom_chasin(text: str): # 1.让大模型生产故事 chain1 = prompt1 | llm | StrOutputParser() output1 = chain1.invoke({"topic": text}) output1 = re.sub(f"<think>.+</think>", '', output1) chain2 = prompt2 | llm | StrOutputParser() return chain2.invoke({"poem": output1}) res = custom_chasin.invoke({"text": "好好学习"}) print(res)
RunnablePassthrough
from langchain_core.runnables import RunnablePassthrough,RunnableParallel """ RunnablePassthrough 功能特点 透传数据:接收输入数据,不做修改直接传递给下一个组件 保持原样:输入是什么,输出就是什么 串联作用:主要用于连接其他组件 """ """ lambda 功能特点 Lambda 就是用来创建简单、临时的小函数,不需要专门给它起名字。 用 lambda(简单写法) lambda x: x['num'] + 1 用普通函数(复杂写法) def my_function(x): return x['num'] + 1 """ chain = RunnableParallel( passed = RunnablePassthrough(), modified=lambda x:x['num'] + 1, extra =RunnablePassthrough.assign(count=lambda x: x['num'] * 2) ) res = chain.invoke({'num':1}) print(res)
ConfigurableField--动态调整大模型参数
from langchain_core.runnables import ConfigurableField from langchain_ollama import ChatOllama from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser """ ConfigurableField 是一个可配置字段装饰器,用于标记LLM模型中可以在运行时动态调整的参数。 核心功能 参数外置:将模型参数(如temperature)从硬编码转为外部可配置 运行时调整:允许在调用时动态修改参数值 统一管理:通过config参数集中传递配置项 ConfigurableField 可调整的大模型参数 核心参数类别 1. 采样参数 temperature:控制输出随机性(0-2.0) top_p:核采样阈值,控制考虑词汇的概率累积 top_k:限制候选词数量,只考虑前k个最可能的词 2. 输出长度控制 max_tokens:最大输出token数 min_tokens:最小输出token数 max_new_tokens:新增token的最大数量 3. 重复惩罚参数 repetition_penalty:重复内容惩罚系数 presence_penalty:已出现token的惩罚 frequency_penalty:高频token的惩罚 4. 搜索策略 num_beams:束搜索宽度 do_sample:是否启用采样(vs贪婪解码) early_stopping:提前停止策略 """ llm = ChatOllama(model="qwen3:1.7b").configurable_fields( temperature=ConfigurableField("temperature") ) prompt = PromptTemplate.from_template("生产一个大于{x}的随机数。\n/no_think") chain = prompt | llm | StrOutputParser() # 调整顺序:先prompt,再llm,最后解析 res = chain.invoke({"x": 5}, config={"configurable":{"temperature": 0.8}}) print(res)
短期记忆--InMemoryChatMessageHistory--单个key
from langchain_ollama import ChatOllama from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_core.chat_history import BaseChatMessageHistory,InMemoryChatMessageHistory llm = ChatOllama(model="qwen3:1.7b") # 保存短期的al的会话 sessions = {} prompt_template = ChatPromptTemplate.from_messages([ ("system", "你是{major}领域的专家"), MessagesPlaceholder(variable_name="history"), ("user", "{question}") ]) chain = prompt_template | llm | StrOutputParser() def get_session_history(session_id: str) -> BaseChatMessageHistory: if session_id not in sessions: sessions[session_id] = InMemoryChatMessageHistory () return sessions[session_id] runnable_with_history = RunnableWithMessageHistory( runnable=chain, get_session_history=get_session_history, input_messages_key="question", history_messages_key="history", ) # 1. 第一次和大模型进行交互 for chunk in runnable_with_history.stream( {"major": "古诗", "question": "写一首唐诗"}, config={"configurable": {"session_id": "1"}} ): print(chunk, end="") print() print("="*30) # 2. 第二次和大模型进行交互 for chunk in runnable_with_history.stream( {"major": "古诗", "question": "给古诗1-10分打分"}, config={"configurable": {"session_id": "1"}} ): print(chunk, end="") print() print("="*30) print() print("sessions:",sessions)
短期记忆--InMemoryChatMessageHistory--多个key
from langchain_ollama import ChatOllama from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_core.chat_history import BaseChatMessageHistory,InMemoryChatMessageHistory from langchain_core.runnables import ConfigurableFieldSpec llm = ChatOllama(model="qwen3:1.7b") # 保存短期的al的会话 sessions = {} prompt_template = ChatPromptTemplate.from_messages([ ("system", "你是{major}领域的专家"), MessagesPlaceholder(variable_name="history"), ("user", "{question}") ]) chain = prompt_template | llm | StrOutputParser() def get_session_history(user_id: str, conversation_id: str ) -> BaseChatMessageHistory: if (user_id, conversation_id) not in sessions: sessions[(user_id, conversation_id)] = InMemoryChatMessageHistory () return sessions[(user_id, conversation_id)] """ history_factory_config 的作用 history_factory_config 在你的代码中用于配置会话历史工厂的可配置字段。 具体功能: 定义配置参数:指定哪些参数可以用来区分不同的会话历史 多键值支持:允许同时使用 user_id 和 conversation_id 来唯一标识一个会话 参数验证:为每个配置字段提供类型注解和描述信息 """ """ ConfigurableFieldSpec 的作用 ConfigurableFieldSpec 是 LangChain 中用于定义可配置字段规范的类,主要作用包括: 主要功能: 字段定义:定义可以在运行时配置的参数规格 类型标注:指定参数的数据类型(通过 annotation 参数) 元数据描述:提供字段名称、描述等说明信息 配置验证:确保传入的配置参数符合预期格式 """ runnable_with_history = RunnableWithMessageHistory( runnable=chain, get_session_history=get_session_history, input_messages_key="question", history_messages_key="history", history_factory_config = [ ConfigurableFieldSpec( id= "user_id", name="User ID", annotation= "str", description="用户的id" ), ConfigurableFieldSpec( id= "conversation_id", name="Conversation ID", annotation= "str", description="会话的id" ), ] ) # 1. 第一次和大模型进行交互 for chunk in runnable_with_history.stream( {"major": "古诗", "question": "写一首唐诗"}, config={"configurable": {"user_id": "1", "conversation_id": "10"}} ): print(chunk, end="") print() print("="*30) # 2. 第二次和大模型进行交互 for chunk in runnable_with_history.stream( {"major": "古诗", "question": "给古诗1-10分打分"}, config={"configurable": {"user_id": "1", "conversation_id": "10"}} ): print(chunk, end="") print() print("="*30) print() print("sessions:",sessions)
使用Redis实现长期记忆

解析PDF文档

解析普通PDF
无表格 图片
from langchain_community.document_loaders import PyPDFLoader import os # 使用绝对路径 file_path = r"d:\python-fast-api\langchain\document-loader\resource\game.pdf" # 验证文件是否存在 if os.path.exists(file_path): loader = PyPDFLoader(file_path) pages = [] for page in loader.lazy_load(): pages.append(page) print('查看类型', type(pages[0])) print('查看内容', pages[0]) else: print(f"文件不存在: {file_path}") # 打印当前工作目录供参考 print(f"当前工作目录: {os.getcwd()}")
解析带图片的PDF

import base64 import io import fitz from PIL import Image from langchain_core.messages import HumanMessage from langchain_openai import ChatOpenAI llm = ChatOpenAI( base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key="sk-49b8b768d54446ba9a88126f4a835c53", model="qwen-vl-max", ) def pdf_page_to_base64(pdf_path: str, page_num: int): # 1.加载PDF文件 pad_document = fitz.open(pdf_path) # 2.加载 page_num 页面 page = pad_document.load_page(page_num - 1) # 3.将页面转换为图片 pix = page.get_pixmap() # 4. 转换成pix中的image对象 img = Image.frombytes("RGB", [pix.width, pix.height] , pix.samples) # 5. 将img数据写入到内存缓存中 buffer = io.BytesIO() # 6. 将图片保存到内存缓存中 img.save(buffer, format="PNG") return base64.b64encode(buffer.getvalue()).decode('utf-8') base64_image = pdf_page_to_base64(pdf_path=r"d:\python-fast-api\langchain\document-loader\resource\game.pdf", page_num=2) messages = [ HumanMessage([ {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_image}"}}, {"type": "text", "text": "帮我提取图片中的文字,如果其中有图表,那么将图表上表现的信息也用文字描述"} ]) ] res = llm.invoke(messages) print(res.content)
html文档解析

解析网页html
from langchain_community.document_loaders import WebBaseLoader import bs4 page_url = 'https://cn.vuejs.org/guide/best-practices/performance#reduce-reactivity-overhead-for-large-immutable-structures' loader = WebBaseLoader( web_paths=[page_url], bs_kwargs= {"parse_only": bs4.SoupStrainer(class_= "VPContentDoc has-aside has-sidebar")}, ) for doc in loader.lazy_load(): print(doc)
解析本地html文件
from langchain_community.document_loaders import BSHTMLLoader import bs4 loader = BSHTMLLoader( file_path=r"d:\python-fast-api\langchain\document-loader\resource\example.html" , bs_kwargs={ "parse_only": bs4.SoupStrainer("title"), "features": "html.parser" } ) for doc in loader.lazy_load(): print('解析的文本是', doc)
解析csv文件
from langchain_community.document_loaders import CSVLoader loader = CSVLoader(file_path=r"d:\python-fast-api\langchain\document-loader\resource\mlb_teams_2012.csv", encoding='utf-8') docs = loader.lazy_load() for doc in loader.lazy_load(): print(doc)
文档切片

基于token长度切分
首先安装 pip install langchain-text-splitters==0.3.8
from langchain_text_splitters import TokenTextSplitter from langchain_community.document_loaders import TextLoader loader = TextLoader(file_path='D:/python-fast-api/langchain/text-splitter-demo/yu7.txt', encoding='utf-8') doc = loader.load() splitter = TokenTextSplitter( chunk_size=100, chunk_overlap=10, encoding_name='cl100k_base' # o200k_base和cl100k_base 模型 # cl100k_base 模型是 gpt-3.5-turbo 模型使用的编码器, # 适用于中文。 # o200k_base 模型是 gpt-4 模型使用的编码器, # 适用于英文。 ) # 针对纯文本切割 # texts = splitter.split_text(doc[0].page_content) # 针对文档对象切割 texts = splitter.split_documents(doc) print(texts)
递归切分
from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.document_loaders import TextLoader loader = TextLoader(file_path='D:/python-fast-api/langchain/text-splitter-demo/yu7.txt', encoding='utf-8') docs = loader.load() splitter = RecursiveCharacterTextSplitter( chunk_size=100, chunk_overlap=10, separators=['\n\n', '\n', '(?<=[,。!])', '(?<=[. ; 、])', " ", ""], keep_separator=False, is_separator_regex=True, ) docs = splitter.split_documents(docs) print(docs)
基于语义切分

from langchain_community.document_loaders import TextLoader from langchain_ollama import OllamaEmbeddings from langchain_experimental.text_splitter import SemanticChunker loader = TextLoader(file_path='D:/python-fast-api/langchain/text-splitter-demo/yu7.txt', encoding='utf-8') docs = loader.load() ebeddings = OllamaEmbeddings(model="mistral") splitter = SemanticChunker( embeddings=ebeddings, sentence_split_regex=r"(?<=[.!?,?!]) +", # breakpoint_threshold_amount=8, # breakpoint_threshold_type="standard_deviation", # breakpoint_threshold_amount=8, # breakpoint_threshold_type="interquartile", #四分卫 # breakpoint_threshold_amount=0.5, breakpoint_threshold_type="gradient", #梯度切分 breakpoint_threshold_amount=90, ) res = splitter.split_documents(docs) print(res)

本文来自博客园,作者:樱桃树下的约定,转载请注明原文链接:https://www.cnblogs.com/tcyweb/p/19406516

浙公网安备 33010602011771号