当前位置: 首页 > news >正文

LangChain构建语言模型驱动应用的强大框架

LangChain

  • 核心功能与组件
    • 链(Chains)
    • 记忆(Memory)
    • 提示模板(Prompts)
    • 代理(Agents)
    • 数据检索(Indexes)
  • 应用场景
    • 文档问答
    • 自动化工作流
    • 知识管理系统
  • 发展历程
  • 总结
  • LangChain Cookbook 👨‍🍳👩‍🍳
      • **什么是 LangChain?**
      • **为什么是 LangChain?**
  • LangChain 组件
    • Schema - 使用大型语言模型 (LLM) 的基本知识
      • **文本**
      • **聊天消息**
      • **文档**
    • 模型——人工智能大脑的接口
      • **语言模型**
      • **聊天模型**
      • 函数调用模型
      • **文本嵌入模型**
    • 提示 - 通常用作模型说明的文本
      • **提示**
      • **提示模板**
      • **示例选择器**
      • **输出解析器方法 1:提示指令和字符串解析**
      • **输出解析器方法 2:OpenAI 函数**
    • 索引 - 将文档结构化为 LLM 可以使用它们
      • **文档加载器**
      • **文本分割器**
      • **检索器**
      • **VectorStores**
    • 记忆
      • 聊天消息历史记录
    • 链 ⛓️⛓️⛓️
      • 1. 简单顺序链
      • 2. 总结链
    • Agent 🤖🤖
      • Agent
      • 工具
      • 工具包

LangChain 是一个开源框架,旨在帮助开发者构建基于大型语言模型(LLM)的应用程序。它通过模块化设计和灵活的组件组合,简化了语言模型的集成和应用开发过程。

核心功能与组件

LangChain 提供了一系列强大的功能和组件,以支持从简单到复杂的语言模型应用开发:

链(Chains)

链是 LangChain 的核心机制,通过将多个组件(如语言模型、提示模板、工具等)组合在一起,形成一个自动化的工作流。链可以用于文档问答、多语言翻译、内容生成等多种场景。

记忆(Memory)

LangChain 提供了多种记忆机制,如对话缓冲内存、对话摘要内存等。这些机制能够帮助语言模型在对话过程中保留上下文信息,从而生成更具连贯性和个性化的响应。

提示模板(Prompts)

提示模板是预构建的结构,用于优化语言模型的输入格式。开发者可以通过这些模板为聊天机器人、问答系统等应用提供更精准的指令。

代理(Agents)

代理是一种特殊的链,能够根据用户输入动态调用工具和执行任务。它允许语言模型自主决定完成任务的最佳步骤,适用于复杂的多步推理任务。

数据检索(Indexes)

LangChain 支持构建和操作文档索引,能够将语言模型与外部数据源(如向量数据库)连接起来。这使得模型可以访问最新的数据,而无需重新训练。

应用场景

LangChain 的灵活性使其能够支持多种应用场景,包括但不限于:
聊天机器人:通过记忆和提示模板,构建能够理解上下文的智能聊天助手。

文档问答

结合数据检索功能,实现对特定文档的智能问答。

自动化工作流

通过代理和工具集成,实现复杂的任务自动化。

知识管理系统

构建企业级的知识库,支持智能检索和内容生成。

发展历程

LangChain 由 Harrison Chase 创立,于 2022 年 10 月首次开源。其发展历程可以分为以下几个阶段:
2022 年:最初版本发布,提供基础的提示管理和链式调用功能。
2023 年:快速迭代,推出记忆、代理、RAG 支持等关键功能。
2024 年:进一步优化技术,加强社区建设,推动商业化应用。
LangChain 的成功不仅体现在其技术的先进性,还在于其强大的社区支持和快速的迭代能力。

总结

LangChain 作为语言模型应用开发的框架,凭借其模块化设计和强大的功能组件,为开发者提供了极大的便利。它不仅简化了开发流程,还通过记忆、检索和代理等功能,扩展了语言模型的应用边界。无论是简单的问答系统还是复杂的多步推理任务,LangChain 都能提供有效的解决方案。随着人工智能技术的不断发展,LangChain 有望继续引领语言模型应用开发的潮流。

下面具体的代码演示

LangChain Cookbook 👨‍🍳👩‍🍳

什么是 LangChain?

LangChain 是一个由语言模型驱动的应用程序开发框架。

LangChain 让使用 AI 模型进行工作和构建的复杂部分变得更容易。它通过两种方式帮助实现这一点:

  1. 集成 - 将外部数据(例如文件、其他应用程序和 API 数据)带到您的 LLM
  2. Agent - 允许您的 LLM 通过决策与其环境交互。使用 LLM 来帮助决定下一步要采取什么行动

为什么是 LangChain?

  1. 组件 - LangChain 可以轻松交换使用语言模型所需的抽象和组件。

  2. 定制链 - LangChain 为使用和定制“链”提供开箱即用的支持 - 一系列串联在一起的操作。

  3. 速度🚢 - Langchain团队的更新速度非常快,集成最新的 LLM 功能。

  4. 社区 👥 - 出色的 discord 和社区支持、聚会、黑客马拉松等。

虽然 LLM 可以很简单(文本输入、文本输出),但一旦你需要开发出更复杂的应用程序,很快就会遇到很多问题,此时LangChain可以很好的帮助你解决问题

需要一个 OpenAI api 密钥才能遵循本教程。读者可以将其作为环境变量,放在此 jupyter 笔记本所在的 .env 文件中,或将其插入“YourAPIKey”所在的位置下方。

!pip install -q chromadb
!pip install -q tiktoken
!pip install -qU langchain-openai
!pip install -qU langchain-community
!pip install -q unstructured
import os
from google.colab import userdata
OPENAI_API_KEY=userdata.get('OPENAI_API_KEY')
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY

LangChain 组件

Schema - 使用大型语言模型 (LLM) 的基本知识

文本

与 LLM 交互的自然语言方式

# 你将使用简单的字符串(其复杂性很快就会增加!)
my_text = "星期五之后是星期几?"
my_text
'星期五之后是星期几?'

聊天消息

类似文本,但指定了消息类型(系统、人类、人工智能)

  • 系统(System) - 有用的背景信息,告诉人工智能该做什么
  • 人类(Human) - 旨在代表用户的消息
  • 人工智能(AI) - 显示人工智能响应的内容的消息

有关更多信息,请参阅 OpenAI 的 文档

from langchain_openai import ChatOpenAIfrom langchain.schema import HumanMessage, SystemMessage, AIMessage# 这就是我们将要使用的语言模型。我们将在下一节中讨论我们正在做的事情
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)

现在让我们创建一些消息来模拟与机器人的聊天体验

llm.invoke([SystemMessage(content="你是一个很棒的人工智能机器人,能用一句话帮助用户知道该吃什么"),HumanMessage(content="我喜欢吃西红柿,应该吃什么呢?")]
)
AIMessage(content='你可以尝试做一个新鲜的西红柿鸡蛋汤,简单又美味!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 23, 'prompt_tokens': 44, 'total_tokens': 67, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_5f20662549', 'finish_reason': 'stop', 'logprobs': None}, id='run-8b6991b4-6708-4383-8e0b-cc471bda0b47-0', usage_metadata={'input_tokens': 44, 'output_tokens': 23, 'total_tokens': 67, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

您还可以通过 AI 的回复传递更多聊天记录

llm.invoke([SystemMessage(content="你是一个友好的AI机器人,可以用简短的一句话帮助用户决定去哪里旅行"),HumanMessage(content="我喜欢海滩,我应该去哪里?"),AIMessage(content="你应该去法国尼斯"),HumanMessage(content="我到那里后还应该做些什么?")]
)
AIMessage(content='除了享受海滩,你还可以探索老城、参观马蒂斯博物馆,或者沿着英国大道漫步。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 31, 'prompt_tokens': 62, 'total_tokens': 93, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_5f20662549', 'finish_reason': 'stop', 'logprobs': None}, id='run-b287edd2-fd2f-4123-b87c-4b98f0b962e5-0', usage_metadata={'input_tokens': 62, 'output_tokens': 31, 'total_tokens': 93, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

您还可以根据需要排除系统消息

llm.invoke([HumanMessage(content="星期四之后是星期几?")]
)
AIMessage(content='星期四之后是星期五。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 14, 'total_tokens': 22, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_d28bcae782', 'finish_reason': 'stop', 'logprobs': None}, id='run-985361de-1947-4a77-b4c5-7ed0e55ad56f-0', usage_metadata={'input_tokens': 14, 'output_tokens': 8, 'total_tokens': 22, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

文档

包含一段文本和元数据(有关该文本的更多信息)的对象

from langchain.schema import Document
Document(page_content="这是我的文档。它包括了我从其他地方收集的信息",metadata={'my_document_id' : 234234,'my_document_source' : "LangChain 论文",'my_document_create_time' : 1680013019})
Document(metadata={'my_document_id': 234234, 'my_document_source': 'LangChain 论文', 'my_document_create_time': 1680013019}, page_content='这是我的文档。它包括了我从其他地方收集的信息')

metadata信息不需要被包含

Document(page_content="这是我的文档。它包括了我从其他地方收集的信息")
Document(metadata={}, page_content='这是我的文档。它包括了我从其他地方收集的信息')

模型——人工智能大脑的接口

语言模型

一个输入文本➡️输出文本的模型!

查看我如何将我使用的模型从默认模型更改为gpt-3.5-turbo。可以点击下面链接查看更多模型(https://platform.openai.com/docs/models)

from langchain_openai import ChatOpenAIllm = ChatOpenAI(model_name="gpt-3.5-turbo")
llm.invoke("星期五之后是星期几?")
AIMessage(content='星期五之后是星期六。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 18, 'total_tokens': 30, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-44f66e6c-9688-4662-a7d3-923ed61a58c6-0', usage_metadata={'input_tokens': 18, 'output_tokens': 12, 'total_tokens': 30, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

聊天模型

接收一系列消息并返回消息输出的模型

from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage, AIMessagellm = ChatOpenAI(model_name="gpt-3.5-turbo")
llm.invoke([SystemMessage(content="你是一个毫无帮助的人工智能机器人,无论用户说什么,它都会开玩笑"),HumanMessage(content="我想去上海,应该怎么办?")]
)
AIMessage(content='把右脚放在左脚前面,然后用左脚迈出一步,再重复这个动作直到到达上海。开玩笑的,哈哈!要去上海,你需要先买机票,然后安排住宿和行程。祝你旅途愉快!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 89, 'prompt_tokens': 62, 'total_tokens': 151, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-4dd072f3-6fe0-4b2f-b878-bd32e3b52667-0', usage_metadata={'input_tokens': 62, 'output_tokens': 89, 'total_tokens': 151, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

函数调用模型

函数调用模型 与聊天模型类似,但略有不同。它们经过微调,可提供结构化数据输出。

当对外部服务进行 API 调用或进行提取时,这会派上很大的用场。

llm = ChatOpenAI(model_name="gpt-4o")messages = [SystemMessage(content="你是一个乐于助人的人工智能机器人"),HumanMessage(content="上海现在的天气怎么样?")
]functions=[{"name": "get_current_weather","description": "获取指定位置的当前天气","parameters": {"type": "object","properties": {"location": {"type": "string","description": "城市和州,例如中国上海"},"unit": {"type": "string","enum": ["celsius", "fahrenheit"]}},"required": ["location"]}
}]output = llm.invoke(input=messages, functions=functions)print(output)
content='' additional_kwargs={'function_call': {'arguments': '{"location":"中国上海","unit":"celsius"}', 'name': 'get_current_weather'}, 'refusal': None} response_metadata={'token_usage': {'completion_tokens': 22, 'prompt_tokens': 82, 'total_tokens': 104, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_5f20662549', 'finish_reason': 'function_call', 'logprobs': None} id='run-2bb2b276-beb5-4770-92d5-6c8b3396368c-0' usage_metadata={'input_tokens': 82, 'output_tokens': 22, 'total_tokens': 104, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}

看到传回给我们的额外“additional_kwargs”了吗?我们可以将其传递给外部 API 以获取数据。这省去了进行输出解析的麻烦。

文本嵌入模型

将文本转换为向量(一系列包含文本语义“含义”的数字)。主要用于比较两段文本。

顺便说一句:语义意味着“与语言或逻辑中的含义相关”。

from langchain_openai import OpenAIEmbeddingsembeddings = OpenAIEmbeddings()
text = "今天艳阳高照天气很舒服!"
text_embedding = embeddings.embed_query(text)
print (f"Here's a sample: {text_embedding[:5]}...")
print (f"Your embedding is length {len(text_embedding)}")
Here's a sample: [0.017948752269148827, 0.008655799552798271, 0.006652832496911287, -0.021351424977183342, 0.006696891039609909]...
Your embedding is length 1536

提示 - 通常用作模型说明的文本

提示

需要传递给底层模型的内容

from langchain_openai import ChatOpenAIllm = ChatOpenAI(model_name="gpt-4o")prompt = """
今天是星期一,明天是星期三。这句话有什么问题?
"""print(llm(prompt))
<ipython-input-4-8f4e450524c6>:11: LangChainDeprecationWarning: The method `BaseChatModel.__call__` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.print(llm(prompt))content='这句话有一个明显的问题:逻辑上的不一致。根据常识,今天是星期一,那么明天应该是星期二,而不是星期三。正确的表述应该是:“今天是星期一,明天是星期二。”' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 52, 'prompt_tokens': 24, 'total_tokens': 76, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_50cad350e4', 'finish_reason': 'stop', 'logprobs': None} id='run-699ad99c-bb3a-45f7-9c9d-97058974f0cb-0' usage_metadata={'input_tokens': 24, 'output_tokens': 52, 'total_tokens': 76, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}

提示模板

一个帮助根据用户输入、其他非静态信息和固定模板字符串的组合创建提示的对象。

将其视为 Python 中的 f-string,但用于提示

高级:查看 LangSmithHub(https://smith.langchain.com/hub) 以获取更多社区提示模板

from langchain import PromptTemplatellm = ChatOpenAI(model_name="gpt-4o")# 注意下面的"location",这是稍后另一个值的占位符
template = """
我真的很想去{location}旅行。我应该在那里做什么?用一个简短的句子回复
"""prompt = PromptTemplate(input_variables=["location"],template=template,
)final_prompt = prompt.format(location='上海')print (f"最终提示词: {final_prompt}")
print ("-----------")
print (f"LLM 输出: {llm(final_prompt)}")
最终提示词: 
我真的很想去上海旅行。我应该在那里做什么?用一个简短的句子回复-----------
LLM 输出: content='游览外滩,品尝当地美食,探索豫园和参观东方明珠塔。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 25, 'prompt_tokens': 30, 'total_tokens': 55, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_d28bcae782', 'finish_reason': 'stop', 'logprobs': None} id='run-e38b3647-a03b-46ea-b370-f18a7ead1842-0' usage_metadata={'input_tokens': 30, 'output_tokens': 25, 'total_tokens': 55, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}

示例选择器

一种从一系列示例中进行选择的简单方法,可让您动态地将上下文信息放入提示中。通常在您的任务很细致或您有大量示例时使用。

可以通过下方的链接查看不同类型的示例选择器(https://python.langchain.com/docs/modules/model_io/prompts/example_selectors/)

from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.llms import OpenAIllm = ChatOpenAI(model_name="gpt-4o")example_prompt = PromptTemplate(input_variables=["input", "output"],template="示例输入: {input}\n示例输出: {output}",
)# 名词所在位置的示例
examples = [{"input": "海盗", "output": "船"},{"input": "飞行员", "output": "飞机"},{"input": "司机", "output": "汽车"},{"input": "树", "output": "地面"},{"input": "鸟", "output": "巢"},
]
# SemanticSimilarityExampleSelector 将通过语义含义选择与输入相似的示例example_selector = SemanticSimilarityExampleSelector.from_examples(# 这是可供选择的示例列表。examples,# 这是用于生成嵌入的嵌入类,用于测量语义相似性。OpenAIEmbeddings(),# 这是用于存储嵌入并进行相似性搜索的 VectorStore 类。Chroma,# 这是要生成的示例数量。k=1
)
<ipython-input-6-ed2c96cfdf7f>:8: LangChainDeprecationWarning: The class `OpenAIEmbeddings` was deprecated in LangChain 0.0.9 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-openai package and should be used instead. To use it run `pip install -U :class:`~langchain-openai` and import as `from :class:`~langchain_openai import OpenAIEmbeddings``.OpenAIEmbeddings(),
similar_prompt = FewShotPromptTemplate(# 有助于选择示例的对象example_selector=example_selector,# 你的提示词example_prompt=example_prompt,# 将添加到提示顶部和底部的自定义内容prefix="给出物品通常出现的位置",suffix="Input: {noun}\nOutput:",# 你的提示将收到什么输入input_variables=["noun"],
)
my_noun = "老虎"
my_noun1 = "学生"
my_noun2 = "植物"
print(similar_prompt.format(noun=my_noun))
print("==============")
print(similar_prompt.format(noun=my_noun1))
print("==============")
print(similar_prompt.format(noun=my_noun2))
给出物品通常出现的位置示例输入: 鸟
示例输出: 巢Input: 老虎
Output:
==============
给出物品通常出现的位置示例输入: 司机
示例输出: 汽车Input: 学生
Output:
==============
给出物品通常出现的位置示例输入: 树
示例输出: 地面Input: 植物
Output:
llm(similar_prompt.format(noun=my_noun))
AIMessage(content='丛林', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 36, 'total_tokens': 39, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_50cad350e4', 'finish_reason': 'stop', 'logprobs': None}, id='run-6fb9299a-c365-45f8-94a2-dcb611ad0274-0', usage_metadata={'input_tokens': 36, 'output_tokens': 3, 'total_tokens': 39, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})

输出解析器方法 1:提示指令和字符串解析

一种格式化模型输出的有用方法。通常用于结构化输出。LangChain 在其 文档 中列出了更多输出解析器。

两个大概念:

1. 格式化指令 - 自动生成的提示,告诉 LLM 如何根据您期望的结果格式化其响应

2. 解析器 - 一种将模型的文本输出提取到所需结构(通常是 json)的方法

from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
from pydantic import BaseModel, Field, model_validatormodel = OpenAI(model_name="gpt-3.5-turbo-instruct", temperature=0.0)# 定义你所需的数据结构。
class Joke(BaseModel):setup: str = Field(description="设置笑话的问题")punchline: str = Field(description="解答笑话的答案")# 设置解析器并将指令注入提示模板。
parser = PydanticOutputParser(pydantic_object=Joke)prompt = PromptTemplate(template="回答用户的询问。\n{format_instructions}\n{query}\n",input_variables=["query"],partial_variables={"format_instructions": parser.get_format_instructions()},
)# 一个用于提示语言模型填充数据结构的查询。
prompt_and_model = prompt | model
output = prompt_and_model.invoke({"query": "可以讲个笑话给我听吗?"})
parser.invoke(output)
Joke(setup='为什么熊猫喜欢睡觉?', punchline='因为他们是熊猫,不是熊熊。')

输出解析器方法 2:OpenAI 函数

当 OpenAI 发布函数调用时,游戏发生了变化。这是刚开始时推荐的方法。

他们专门训练模型以输出结构化数据。指定 Pydantic(一种python中的数据验证模式) 模式并获得结构化输出变得非常容易。

有很多方法可以定义你的模式,我更喜欢使用 Pydantic 模型,因为它们的组织性很强。请参考 OpenAI 的 文档 了解其他方法。

使用此方法需要使用支持函数调用的模型。我将使用gpt4-0613

示例 1:简单

让我们从定义一个简单的模型开始,以便从中提取。

from pydantic import BaseModel, Field
from typing import Optionalclass Person(BaseModel):"""关于一个人的身份信息。"""name: str = Field(..., description="该人的姓名")age: int = Field(..., description="该人的年龄")fav_food: Optional[str] = Field(None, description="该人最喜欢的食物")

然后让我们创建一个链(稍后会详细介绍),它将为我们进行提取相关的信息

from langchain_openai import ChatOpenAIllm = ChatOpenAI(model_name="gpt-4o")structured_llm = llm.with_structured_output(Person)
structured_llm.invoke("小丽 13岁,小明刚满 12 岁并且喜欢吃菠菜。 小军比小丽大 10 岁。"
)
Person(name='小丽', age=13, fav_food=None)

注意到我们只有一个人的数据吗?那是因为我们没有指定我们想要多个。让我们更改我们的架构以指定我们想要一个人员列表。

from typing import Sequenceclass People(BaseModel):"""识别文本中所有人物的信息。"""people: Sequence[Person] = Field(..., description="文本中的人物信息")

现在我们将调用People这个大类,而不是之前定义的person,这个People的大类里面包含了Person这个小类

structured_llm = llm.with_structured_output(People)
structured_llm.invoke("小丽 13岁,小明刚满 12 岁并且喜欢吃菠菜。 小军比小丽大 10 岁。"
)
People(people=[Person(name='小丽', age=13, fav_food=None), Person(name='小明', age=12, fav_food='菠菜'), Person(name='小军', age=23, fav_food=None)])

让我们用它做更多解析

示例 2:枚举

现在让我们解析列表中提及的产品

import enumllm = ChatOpenAI(model_name="gpt-4o")class Product(str, enum.Enum):CRM = "CRM"VIDEO_EDITING = "视频剪辑"HARDWARE = "硬件"
class Products(BaseModel):"""识别文本中提到的产品"""products: Sequence[Product] = Field(..., description="文中提到的产品")
structured_llm = llm.with_structured_output(Products)
structured_llm.invoke("这个演示中的 CRM 很棒。喜欢硬件。麦克风也很酷。喜欢视频编辑"
)
Products(products=[<Product.CRM: 'CRM'>, <Product.HARDWARE: '硬件'>, <Product.VIDEO_EDITING: '视频剪辑'>])

索引 - 将文档结构化为 LLM 可以使用它们

文档加载器

从其他来源导入数据的一系列简单方法。与 OpenAI 插件 特别是检索插件 共享功能

可以访问下面的网站查看文档加载器的更多信息(https://python.langchain.com/en/latest/modules/indexes/document_loaders.html)。

Llama Index另外一个类似langchain的框架,主要是索引和提取 上还有更多的信息

网站帖子

from langchain.document_loaders import HNLoader
WARNING:langchain_community.utils.user_agent:USER_AGENT environment variable not set, consider setting it to identify your requests.
loader = HNLoader("https://news.ycombinator.com/item?id=34422627")
data = loader.load()
print (f"发现 {len(data)} 评论")
print (f"以下是一个示例:\n\n{''.join([x.page_content[:150] for x in data[:2]])}")
发现 76 评论
以下是一个示例:Ozzie_osman on Jan 18, 2023  | next [–] LangChain is awesome. For people not sure what it's doing, large language models (LLMs) are veOzzie_osman on Jan 18, 2023  | parent | next [–] Also, another library to check out is GPT Index (https://github.com/jerryjliu/gpt_ind

电子书

from langchain.document_loaders import GutenbergLoaderloader = GutenbergLoader("https://www.gutenberg.org/cache/epub/2148/pg2148.txt")data = loader.load()
print(data[0].page_content[1855:1984])
o.—_Seneca_.At Paris, just after dark one gusty evening in the autumn of 18-,I was enjoying the twofold l

URL 和网页

让我们在 Paul Graham 的网站 上尝试一下

from langchain.document_loaders import UnstructuredURLLoaderurls = ["http://www.paulgraham.com/",
]loader = UnstructuredURLLoader(urls=urls)data = loader.load()data[0].page_content
'New: Writes and Write-Nots | Founder Mode Want to start a startup? Get funded by Y Combinator . © mmxxv pg'

文本分割器

通常的文档对于基本上所有的LLM 来说都太长(就像一本书)。因此需要将其分割成块。文本分割器可帮助完成此操作。

可以通过多种方式将文本分割成块,可以访问下面的链接(https://python.langchain.com/v0.1/docs/modules/data_connection/document_transformers/code_splitter/) 中不同的方法来确定哪种方法最适合。

from langchain.text_splitter import RecursiveCharacterTextSplitter
# 这是一个很长的文档
with open('/content/Xiyouji.txt') as f:pg_work = f.read()print (f"你有 {len([pg_work])} 个文档")
你有 1 个文档
text_splitter = RecursiveCharacterTextSplitter(# 定义chunk size.chunk_size = 500,chunk_overlap  = 20,
)texts = text_splitter.create_documents([pg_work])
print (f"你有 {len(texts)} 个文档")
你有 1784 个文档
print ("前言:")
print (texts[0].page_content, "\n")
print (texts[1].page_content)
前言:
第一回     靈根育孕源流出 心性修持大道生詩曰:混沌未分天地亂,茫茫渺渺無人見。自從盤古破鴻濛,開闢從茲清濁辨。覆載群生仰至仁,發明萬物皆成善。欲知造化會元功,須看西遊釋厄傳。 蓋聞天地之數,有十二萬九千六百歲為一元。將一元分為十二會,乃子、丑、寅
、卯、辰、巳、午、未、申、酉、戌、亥之十二支也。每會該一萬八百歲。且就
一日而論:子時得陽氣,而丑則雞鳴﹔寅不通光,而卯則日出﹔辰時食後,而巳
則挨排﹔日午天中,而未則西蹉﹔申時晡,而日落酉,戌黃昏,而人定亥。譬於
大數,若到戌會之終,則天地昏曚而萬物否矣。再去五千四百歲,交亥會之初,
則當黑暗,而兩間人物俱無矣,故曰混沌。又五千四百歲,亥會將終,貞下起元
,近子之會,而復逐漸開明。邵康節曰::「冬至子之半,天心無改移。一陽初
動處,萬物未生時。」到此,天始有根。再五千四百歲,正當子會,輕清上騰,
有日,有月,有星,有辰。日、月、星、辰,謂之四象。故曰,天開於子。又經
五千四百歲,子會將終,近丑之會,而逐漸堅實。《易》曰:「大哉乾元!至哉
坤元!萬物資生,乃順承天。」至此,地始凝結。再五千四百歲,正當丑會,重
濁下凝,有水,有火,有山,有石,有土。水、火、山、石、土,謂之五形。故
曰,地闢於丑。又經五千四百歲,丑會終而寅會之初,發生萬物。曆曰:「天氣

文本分割的方法有很多种,这取决于检索策略和应用程序设计。可以访问下面的链接查看更多分割器(https://python.langchain.com/v0.1/docs/modules/data_connection/document_transformers/)

检索器

将文档与语言模型相结合的简单方法。
检索器有很多种类型,其中最广泛支持的是 VectorStoreRetriever

from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddingsloader = TextLoader('data/PaulGrahamEssays/worked.txt')
documents = loader.load()
# Get your splitter ready
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)# Split your docs into texts
texts = text_splitter.split_documents(documents)# Get embedding engine ready
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)# Embedd your texts
db = FAISS.from_documents(texts, embeddings)
# Init your retriever. Asking for just 1 document back
retriever = db.as_retriever()
retriever
VectorStoreRetriever(tags=['FAISS'], vectorstore=<langchain.vectorstores.faiss.FAISS object at 0x7f8389169070>)
docs = retriever.get_relevant_documents("what types of things did the author want to build?")
print("\n\n".join([x.page_content[:200] for x in docs[:2]]))
standards; what was the point? No one else wanted one either, so
off they went. That was what happened to systems work.I wanted not just to build things, but to build things that would
last.In this dimuch of it in grad school.Computer Science is an uneasy alliance between two halves, theory
and systems. The theory people prove things, and the systems people
build things. I wanted to build things. 

VectorStores

用于存储向量的数据库。最流行的是 Pinecone 和 Weaviate。OpenAIs retriever 文档 上有更多示例。Chroma 和 FAISS 易于本地使用。

从概念上讲,将它们视为带有嵌入(向量)列和元数据列的表格。

示例

嵌入元数据
[-0.00015641732898075134, -0.003165106289088726, …]{‘日期’ : '1/2/23}
[-0.00035465431654651654, 1.4654131651654516546, …]{‘日期’ : '1/3/23}
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddingsloader = TextLoader('data/PaulGrahamEssays/worked.txt')
documents = loader.load()# Get your splitter ready
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)# Split your docs into texts
texts = text_splitter.split_documents(documents)# Get embedding engine ready
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
print (f"You have {len(texts)} documents")
You have 78 documents
embedding_list = embeddings.embed_documents([text.page_content for text in texts])
print (f"You have {len(embedding_list)} embeddings")
print (f"Here's a sample of one: {embedding_list[0][:3]}...")
You have 78 embeddings
Here's a sample of one: [-0.001058628615053026, -0.01118234211553424, -0.012874804746266883]...

你的 vectorstore 存储你的嵌入(☝️)并使它们易于搜索

记忆

帮助 LLM 记住信息。

记忆是一个有点宽泛的术语。它可以简单到记住你过去聊过的信息,也可以更复杂地检索信息。

我们将把它放在聊天消息用例中。这将用于聊天机器人。

记忆有很多种类型,可以访问下面的链接(https://python.langchain.com/v0.1/docs/modules/memory/),看看哪一种适合特定的用例。

聊天消息历史记录

from langchain.memory import ChatMessageHistory
from langchain.chat_models import ChatOpenAIchat = ChatOpenAI(temperature=0, openai_api_key=openai_api_key)history = ChatMessageHistory()history.add_ai_message("hi!")history.add_user_message("what is the capital of france?")
history.messages
[AIMessage(content='hi!'),HumanMessage(content='what is the capital of france?')]
ai_response = chat(history.messages)
ai_response
AIMessage(content='The capital of France is Paris.')
history.add_ai_message(ai_response.content)
history.messages
[AIMessage(content='hi!'),HumanMessage(content='what is the capital of france?'),AIMessage(content='The capital of France is Paris.')]

链 ⛓️⛓️⛓️

自动组合不同的 LLM 调用和操作

例如:摘要 #1、摘要 #2、摘要 #3 > 最终摘要

可以查看下面的链接(https://python.langchain.com/v0.1/docs/modules/chains/),搜索看看哪个最适合你自己的用例。

我们将介绍其中两个非常有代表性的:

1. 简单顺序链

简单的链可以将 LLM 的输出用作另一个的输入。适合分解任务(让LLM一次完成一项任务)

from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains import SimpleSequentialChainllm = OpenAI(temperature=1, openai_api_key=openai_api_key)
template = """Your job is to come up with a classic dish from the area that the users suggests.
% USER LOCATION
{user_location}YOUR RESPONSE:
"""
prompt_template = PromptTemplate(input_variables=["user_location"], template=template)# Holds my 'location' chain
location_chain = LLMChain(llm=llm, prompt=prompt_template)
template = """Given a meal, give a short and simple recipe on how to make that dish at home.
% MEAL
{user_meal}YOUR RESPONSE:
"""
prompt_template = PromptTemplate(input_variables=["user_meal"], template=template)# Holds my 'meal' chain
meal_chain = LLMChain(llm=llm, prompt=prompt_template)
overall_chain = SimpleSequentialChain(chains=[location_chain, meal_chain], verbose=True)
review = overall_chain.run("Rome")
[1m> Entering new SimpleSequentialChain chain...[0m
[36;1m[1;3m
A classic dish from Rome is Spaghetti alla Carbonara, featuring egg, Parmesan cheese, black pepper, and pancetta or guanciale.[0m
[33;1m[1;3m
Ingredients:
- 8oz spaghetti 
- 4 tablespoons olive oil
- 4oz diced pancetta or guanciale
- 2 cloves garlic, minced
- 2 eggs, lightly beaten
- 2 tablespoons parsley, chopped 
- ½ cup grated Parmesan 
- Salt and black pepper to tasteInstructions:
1. Bring a pot of salted water to a boil and add the spaghetti. Cook according to package directions. 
2. Meanwhile, add the olive oil to a large skillet over medium-high heat. Add the diced pancetta and garlic, and cook until pancetta is browned and garlic is fragrant.
3. In a medium bowl, whisk together the eggs, parsley, Parmesan, and salt and pepper.
4. Drain the cooked spaghetti and add it to the skillet with the pancetta and garlic. Remove from heat and pour the egg mixture over the spaghetti, stirring to combine. 
5. Serve the spaghetti alla carbonara with additional Parmesan cheese and black pepper.[0m[1m> Finished chain.[0m

2. 总结链

轻松浏览大量长文档并获取总结。查看此视频 了解除 map-reduce 之外的其他链类型

from langchain.chains.summarize import load_summarize_chain
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitterloader = TextLoader('data/PaulGrahamEssays/disc.txt')
documents = loader.load()# Get your splitter ready
text_splitter = RecursiveCharacterTextSplitter(chunk_size=700, chunk_overlap=50)# Split your docs into texts
texts = text_splitter.split_documents(documents)# There is a lot of complexity hidden in this one line. I encourage you to check out the video above for more detail
chain = load_summarize_chain(llm, chain_type="map_reduce", verbose=True)
chain.run(texts)
[1m> Entering new MapReduceDocumentsChain chain...[0m[1m> Entering new LLMChain chain...[0m
Prompt after formatting:
[32;1m[1;3mWrite a concise summary of the following:"January 2017Because biographies of famous scientists tend to 
edit out their mistakes, we underestimate the 
degree of risk they were willing to take.
And because anything a famous scientist did that
wasn't a mistake has probably now become the
conventional wisdom, those choices don't
seem risky either.Biographies of Newton, for example, understandably focus
more on physics than alchemy or theology.
The impression we get is that his unerring judgment
led him straight to truths no one else had noticed.
How to explain all the time he spent on alchemy
and theology?  Well, smart people are often kind of
crazy.But maybe there is a simpler explanation. Maybe"CONCISE SUMMARY:[0m
Prompt after formatting:
[32;1m[1;3mWrite a concise summary of the following:"the smartness and the craziness were not as separate
as we think. Physics seems to us a promising thing
to work on, and alchemy and theology obvious wastes
of time. But that's because we know how things
turned out. In Newton's day the three problems 
seemed roughly equally promising. No one knew yet
what the payoff would be for inventing what we
now call physics; if they had, more people would 
have been working on it. And alchemy and theology
were still then in the category Marc Andreessen would 
describe as "huge, if true."Newton made three bets. One of them worked. But 
they were all risky."CONCISE SUMMARY:[0m[1m> Finished chain.[0m[1m> Entering new LLMChain chain...[0m
Prompt after formatting:
[32;1m[1;3mWrite a concise summary of the following:" Biographies of famous scientists often edit out their mistakes, giving readers the wrong impression that they never faced any risks to achieve successful results. An example of this is Newton, whose smartness is assumed to have led straight him to truths without any detours into alchemy or theology - despite the fact that he spent a lot of time on both fields. Maybe the simpler explanation is that he was willing to take risks, even if it means potentially making mistakes.In the 17th century, Newton took a risk and made three bets, one of which turned out to be a successful invention of what we now call physics. The other two bets were on less popular subjects of the time such as alchemy and theology. People did not know then what the payoff would be, but the bets still seemed relatively promising."CONCISE SUMMARY:[0m[1m> Finished chain.[0m[1m> Finished chain.[0m" Biographies tend to omit famous scientists' mistakes from their stories, but Newton was willing to take risks and explore multiple fields to make his discoveries. He placed three risky bets, one of which resulted in the creation of physics as we know it today."

Agent 🤖🤖

官方 LangChain 文档完美地描述了Agent的概念:

一些应用程序不仅需要对 LLM/其他工具的预定调用链,还可能需要依赖于用户输入的未知链。在这些类型的链中,有一个可以访问一套工具的“Agent”。根据用户输入,Agent可以**决定调用这些工具中的哪一个(如果有的话)。

基本上Agent不仅将 LLM 用于文本输出,还用于决策。此功能的酷炫和强大怎么强调都不为过。

Sam Altman 强调 LLM 是优秀的“推理引擎”。Agent的出现正是利用了这一点。

Agent

驱动决策的语言模型。

更具体地说,Agent接收输入并返回与要采取的操作以及操作输入相对应的响应。可以访问下面的链接(https://python.langchain.com/v0.1/docs/modules/agents/agent_types/) 看到不同类型的Agent(它们更适合不同的用例)。

工具

Agent的“功能”。这是函数顶部的抽象,使 LLM(和Agent)能够轻松与其交互。例如:Google 搜索。

此区域与 OpenAI 插件 有共同之处。

工具包

一个特定的Agent可以从中选择的工具组

让我们将它们整合在一起:

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.llms import OpenAI
import jsonllm = OpenAI(temperature=0, openai_api_key=openai_api_key)
serpapi_api_key=os.getenv("SERP_API_KEY", "YourAPIKey")
toolkit = load_tools(["serpapi"], llm=llm, serpapi_api_key=serpapi_api_key)
agent = initialize_agent(toolkit, llm, agent="zero-shot-react-description", verbose=True, return_intermediate_steps=True)
response = agent({"input":"what was the first album of the""band that Natalie Bergman is a part of?"})
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I should try to find out what band Natalie Bergman is a part of.
Action: Search
Action Input: "Natalie Bergman band"[0m
Observation: [36;1m[1;3m['Natalie Bergman is an American singer-songwriter. She is one half of the duo Wild Belle, along with her brother Elliot Bergman. Her debut solo album, Mercy, was released on Third Man Records on May 7, 2021. She is based in Los Angeles.', 'Natalie Bergman type: American singer-songwriter.', 'Natalie Bergman main_tab_text: Overview.', 'Natalie Bergman kgmid: /m/0qgx4kh.', 'Natalie Bergman genre: Folk.', 'Natalie Bergman parents: Susan Bergman, Judson Bergman.', 'Natalie Bergman born: 1988 or 1989 (age 34–35).', 'Natalie Bergman is an American singer-songwriter. She is one half of the duo Wild Belle, along with her brother Elliot Bergman. Her debut solo album, Mercy, ...'][0m
Thought:[32;1m[1;3m I should search for the first album of Wild Belle
Action: Search
Action Input: "Wild Belle first album"[0m
Observation: [36;1m[1;3mIsles[0m
Thought:[32;1m[1;3m I now know the final answer
Final Answer: Isles is the first album of the band that Natalie Bergman is a part of.[0m[1m> Finished chain.[0m

相关文章:

LangChain构建语言模型驱动应用的强大框架

LangChain 核心功能与组件链&#xff08;Chains&#xff09;记忆&#xff08;Memory&#xff09;提示模板&#xff08;Prompts&#xff09;代理&#xff08;Agents&#xff09;数据检索&#xff08;Indexes&#xff09; 应用场景文档问答自动化工作流知识管理系统 发展历程总结…...

2025-03-08 学习记录--C/C++-PTA 习题10-2 递归求阶乘和

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>double fact( int n ); double facts…...

浅谈 DeepSeek 对 DBA 的影响

引言&#xff1a; 在人工智能技术飞速发展的背景下&#xff0c;DeepSeek 作为一款基于混合专家模型&#xff08;MoE&#xff09;和强化学习技术的大语言模型&#xff0c;正在重塑传统数据库管理&#xff08;DBA&#xff09;的工作模式。通过结合其强大的自然语言处理能力、推理…...

AI如何重塑运维体系

AI大模型的引入正在从被动响应到主动预防、从经验驱动到数据智能全面重构运维体系。 一、颠覆传统运维模式的技术革新 故障预测&#xff1a;从“救火”到“防火” AI大模型通过整合历史日志、硬件状态、网络流量等多模态数据&#xff0c;结合时间序列分析&#xff08;如LSTM&am…...

linux 内网下载 yum 依赖问题

1.上传系统镜像 创建系统目录&#xff0c;用户存放镜像&#xff0c;如下&#xff1a; mkdir /mnt/iso上传 iso 文件到 /mnt/iso 文件夹下。 2.挂载系统镜像 安装镜像至 /mnt/cdrom 目录中 mount -o loop /mnt/iso/CentOS-7-x86_64-Minimal-xx.iso /mnt/cdrom3.修改yum源配…...

mapbox开发小技巧

自定义图标 // 1、单个图标 const url ./static/assets/symbols/code24x24/VIDEO.png // 图标路径 map.loadImage(url ,(error, image) > {if (error) throw errormap.addImage(video-icon, image) })// 2、雪碧图利用canvas // json和png图片 function getStyleImage(fil…...

DeepSeek×博云AIOS:突破算力桎梏,开启AI普惠新纪元

背景 在全球人工智能技术高速迭代的背景下&#xff0c;算力成本高企、异构资源适配复杂、模型部署效率低下等问题&#xff0c;始终是制约企业AI规模化应用的关键。 DeepSeek以创新技术直击产业痛点&#xff0c;而博云先进算力管理平台AIOS的全面适配&#xff0c;则为这一技术…...

Java高频面试之集合-07

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;ArrayList 和 Vector 的区别是什么&#xff1f; ArrayList 与 Vector 的区别详解 ArrayList 和 Vector 都是 Java 中基于…...

Redis- 切片集群

切片集群 切片集群什么是Redis Cluster吗&#xff1f;为什么需要切片集群&#xff1f;Redis Cluster的数据分片机制是怎样的&#xff1f;哈希槽的算法是什么基本算法流程 待填坑 切片集群 什么是Redis Cluster吗&#xff1f;为什么需要切片集群&#xff1f; Redis Cluster是R…...

【项目日记(十)】瓶颈分析与使用基数树优化

前言 上一期我们对整个项目进行了细节部分的优化&#xff0c;并在最后测试了多线程环境下和malloc的性能对比测试&#xff0c;发现malloc有时候还是更胜一筹的&#xff0c;基于此我们进行对我们的内存池进行瓶颈分析与优化。 目录 前言 一、项目瓶颈分析 VS编译器下性能分…...

后台管理系统比较全面的分析对比

以下是主流的 后台管理系统模板 分类与技术选型指南&#xff0c;涵盖开源、商业及全栈解决方案&#xff0c;可根据项目需求灵活选择&#xff1a; 一、开源免费模板 1. React 技术栈 Ant Design Pro 官网&#xff1a;pro.ant.design特点&#xff1a;阿里出品&#xff0c;内置 R…...

HCIA复习拓扑实验

一.拓扑图 二.需求 1.学校内部的HTTP客户端可以正常通过域名www.baidu.com访问到百度网络中HTTP服务器 2.学校网络内部网段基于192.168.1.0/24划分&#xff0c;PC1可以正常访问3.3.3.0/24网段&#xff0c;但是PC2不允许 3.学校内部路由使用静态路由&#xff0c;R1和R2之间两…...

TI毫米波雷达开发 —— 串口输出数据解析

TI毫米波雷达开发 —— 串口输出解析 TLV协议协议概述HeaderBodyPadding TI 毫米波雷达芯片计算的结果数据都会从UART发出供上位机进行解析并展示。解析和展示是两个不同的概念&#xff0c;解析指提取有效数据并转换成常见的度量值。展示指数据的可视化。 由于雷达这个领域的特…...

Docker Desktop 4.38 安装与配置全流程指南(Windows平台)

一、软件定位与特性 Docker Desktop 是容器化应用开发与部署的一体化工具&#xff0c;支持在本地环境创建、管理和运行Docker容器。4.38版本新增GPU加速支持、WSL 2性能优化和Kubernetes 1.28集群管理功能&#xff0c;适用于微服务开发、CI/CD流水线搭建等场景。 二、安装环境…...

【AD】5-16 泪滴的添加

1.工具—滴泪&#xff08;快捷键TE&#xff09;...

聊天服务器分布式改造

目前的聊天室是单节点的&#xff0c;无论是http接口还是socket接口都在同一个进程&#xff0c;无法承受太多人同时在线&#xff0c;容灾性也非常差。因此&#xff0c;一个成熟的IM产品一定是做成分布式的&#xff0c;根据功能分模块&#xff0c;每个模块也使用多个节点并行部署…...

el-table(elementui)表格合计行使用以及滚动条默认样式修改

一、el-table新增合计行以及el-table展示数据出现的问题 1. 使用合计行 el-table的属性show-summary设为true&#xff0c;即可在表格尾部展示合计行。默认情况下&#xff0c;第一列不展示数据&#xff0c;而显示合计二字&#xff0c;可以通过sum-text自己配置&#xff0c;其余…...

Web前端开发——HTML基础下

HTML语法 一表格1.基本格式2.美化表格合并居中属性 二表单1.input2.select3.textarea4.button5.date6.color7.checkbox8.radio9.range10.number 一表格 1.基本格式 HTML表格由<table>标签定义 其中行由<tr>标签定义&#xff0c;单元格由<td>定义。我们先来…...

Python使用入门(一)

初识数据类型 整型(int) print(666) print(2 10) print(2 * 12)字符串(str) 单行字符串 #单行字符串 print("我是小红aaa") print(我是小红aaa)print("中国上海") print(中国上海)# 输出带引号的字符串 print(我是"小红aaa) print("我是\&qu…...

基于multisim的花样彩灯循环控制电路设计与仿真

1 课程设计的任务与要求 &#xff08;一&#xff09;、设计内容&#xff1a; 设计一个8路移存型彩灯控制器&#xff0c;基本要求&#xff1a; 1. 8路彩灯能演示至少三种花型&#xff08;花型自拟&#xff09;&#xff1b; 2. 彩灯用发光二极管LED模拟&#xff1b; 3. 选做…...

求最大公约数【C/C++】

大家好啊&#xff0c;欢迎来到本博客( •̀ ω •́ )✧&#xff0c;我将带领大家详细的了解最大公约数的思想与解法。 一、什么是公约数 公约数&#xff0c;也称为公因数&#xff0c;是指两个或多个整数共有的因数。具体来说&#xff0c;如果一个整数能被两个或多个整数整除&…...

leetcode day27 455+376

455 分发饼干 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有…...

go的grpc

GRPC介绍 目录 单体架构微服务架构问题原始的grpc 服务端客户端原生rpc的问题 grpc的hello world 服务端客户端 proto文件proto语法 数据类型 基本数据类型其他数据类型 编写风格多服务 单体架构 只能对整体扩容一荣俱荣&#xff0c;一损俱损代码耦合&#xff0c;项目的开…...

算法每日一练 (9)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 算法每日一练 (9)最小路径和题目描述解题思路解题代码…...

软考高级信息系统项目管理师笔记-第10章项目进度管理

第10章项目进度管理 10.1 管理基础 10.1.1 项目进度计划的定义和总要求 1、项目进度计划是 一种用于沟通和管理干系人期望的工具,为绩效报告提供依据。 2、项目管理团队编制进度计划的一般步骤为: 首先选择进度计划方法,例如关键路径法; 然后将项目特定数据,如活动、计…...

专门为高速连续扫描设计的TDI工业相机

TDI&#xff08;Time Delay Integration&#xff0c;时间延迟积分&#xff09;工业相机是一种基于特殊CCD&#xff08;电荷耦合器件&#xff09;技术的成像设备&#xff0c;主要用于高速、高灵敏度、高分辨率的图像采集场景。其核心原理是通过多级积分和同步电荷转移技术&#…...

【Vue3】实现一个超过高度后可控制显示隐藏的组件

组件效果图 未达到最大高度 达到设置的最大高度 进行展开 实现代码 组件代码 备注&#xff1a;通过tailwindcss设置的样式&#xff0c;通过element-plus/icons-vue设置的图标&#xff0c;可根据情况进行替换 <template><!-- 限制高度组件 --><div ref"…...

Spring提供的SPEL表达式

SPEL 1. 概述 SpEL是Spring框架中用于表达式语言的一种方式。它类似于其他编程语言中的表达式语言&#xff0c;用于在运行时计算值或执行特定任务。 SpEL提供了一种简单且强大的方式来访问和操作对象的属性、调用对象的方法&#xff0c;以及实现运算、条件判断等操作。它可以…...

JAVA编程【jvm垃圾回收的差异】

jvm垃圾回收的差异 JVM&#xff08;Java Virtual Machine&#xff09;的垃圾回收&#xff08;GC&#xff09;机制是自动管理内存的一种方式&#xff0c;能够帮助开发者释放不再使用的内存&#xff0c;避免内存泄漏和溢出等问题。不同的垃圾回收器&#xff08;GC&#xff09;有…...

Elasticsearch:“Your trial license is expired”

目录标题 问题原因解决方案 问题 原因 ES的X-pack许可证是提供免费一个月的试用&#xff0c;到期之后就会报这个错误。 解决方案 查看license GET _license 开启试用license POST _xpack/license/start_trial?acknowledgetrue修改为基础license POST _xpack/license/start_…...