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

【LangChain】理论及应用实战(7):LCEL

文章目录

  • 一、LCEL简介
  • 二、LCEL示例
    • 2.1 一个简单的示例
    • 2.2 RAG Search
  • 三、LCEL下核心组件(Prompt+LLM)的实现
    • 3.1 单链结构
    • 3.2 使用Runnables来连接多链结构
      • 3.2.1 连接多链
      • 3.2.2 多链执行与结果合并
      • 3.2.3 查询SQL
    • 3.3 自定义输出解析器
  • 四、LCEL添加Memory
    • 4.1 短时记忆
    • 4.2 长时记忆
  • 五、LCEL:Agent核心组件
    • 5.1 第一个Agent
    • 5.2 Agent案例2

一、LCEL简介

LangChain 表达式语言(LangChain Expression Language,简称 LCEL)是 LangChain 框架中的一个核心组件,旨在提供一种简洁、灵活的方式来定义和操作语言模型的工作流。LCEL 允许开发者以声明式的方式构建复杂的语言模型应用,而无需编写大量的样板代码。

在这里插入图片描述

以下是 LCEL 的主要优势:

  1. 异步、批处理和流支持:采用LCEL构建的任何链都将自动、完全的支持同步、异步、批处理和流等能力。这使得可以在Jupyter中使用同步接口创建链变得很容易,然后将其作为异步流接口进行公开。
  2. Fallbacks:由于LLMs的非确定性,使得具备优雅地处理错误的能力变得很重要。通过LCEL,可以轻松地为任何链添加Fallbacks。
  3. 并行性:由于LLMs应用涉及(有时长期的)API调用,因此支持并行处理很重要。使用LCEL,任何可以并行处理的组件都会自动并行处理。
  4. 无缝集成LangSmith:使用LCEL,所有步骤都会自动记录到LangSmith中,可以最大限度的实现可观察性和可调试性。从而尽量避免因为越来越复杂的链,带来的维护困难。

LCEL包含了多个核心组件,如Prompt, ChatModel, LLM, OutputParser, Retriever, Tool。其为了方便自定义Chain,创造了Runnable协议。Runnable协议适用于大多数组件,是一个标准接口,可以轻松地自定义链并以标准方式调用它们。

我们来看看官网对 Runnable类 的定义:A unit of work that can be invoked, batched, streamed, transformed and composed.
Key Methods(关键方法):

  • invoke/ainvoke: Transforms a single input into an output.
  • batch/abatch: Efficiently transforms multiple inputs into outputs.
  • stream/astream: Streams output from a single input as it’s produced.
  • astream_log: Streams output and selected intermediate results from an input.

在这里插入图片描述

LCEL核心组件的运行流程:
在这里插入图片描述

二、LCEL示例

LCEL使用“|”运算符链接LangChain应用的各个组件。

2.1 一个简单的示例

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLMprompt = PromptTemplate.from_template("tell me a short joke about {topic}")
model = OllamaLLM(model="llama3.1:8b")
output_parser = StrOutputParser()chain = prompt | model | output_parser  # LCEL语法result = chain.invoke({"topic": "ice cream"})
print(result)

输出如下:

Why did the ice cream go to therapy?Because it was feeling a little "melted" under pressure!

可以看到,基于LCEL语法形式来定义Chain,比之前我们复写基类的方式来自定义Chain简单了很多。

2.2 RAG Search

主要是实现以下功能:

  1. 建立向量数据
  2. 使用RAG增强

首先安装依赖包:

pip install --upgrade --quiet langchain langchain-openai faiss-cpu tiktoken

示例代码:

from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_ollama import OllamaLLM, OllamaEmbeddingsvectorstore = FAISS.from_texts(texts=["harrison worked at London"],embedding=OllamaEmbeddings(model="nomic-embed-text:latest")
)
retriever = vectorstore.as_retriever()template = """Answer the question based only on the following context:
{context}Question: {question}
"""prompt = ChatPromptTemplate.from_template(template)model = OllamaLLM(model="llama3.1:8b")chain = ({"context": retriever, "question": RunnablePassthrough()}| prompt| model| StrOutputParser()
)result = chain.invoke("where did harrison work?")
print(result)

输出如下:

London.

【RunnablePassthrough 介绍】,来自官网:https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.passthrough.RunnablePassthrough.html

  • Runnable to passthrough inputs unchanged or with additional keys. This Runnable behaves almost like the identity function, except that it can be configured to add additional keys to the output, if the input is a dict.
  • 翻译一下:RunnablePassthrough 可运行以不改变输入或使用其他键传递输入。这个Runnable的行为几乎类似于identity函数,除了如果输入是dict,它可以被配置为向输出添加额外的键。

我们对上面的代码做个简单的解释:

  • chain.invoke("where did harrison work?") :该函数接收到了变量 question = "where did harrison work?"
  • "question": RunnablePassthrough():使用变量 question 为 key,所以它的 value 接收到了 question 的取值,也就是 "where did harrison work?"

我们现在要求其用指定的语言回答我们的问题,可以对上面的代码进行修改,加入 language 相关的代码。如下:

from operator import itemgetter
from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_ollama import OllamaLLM, OllamaEmbeddingsvectorstore = FAISS.from_texts(texts=["harrison worked at London"],embedding=OllamaEmbeddings(model="nomic-embed-text:latest")
)
retriever = vectorstore.as_retriever()template = """Answer the question based only on the following context:
{context}Question: {question}Answer in the following language: {language}
"""prompt = ChatPromptTemplate.from_template(template)model = OllamaLLM(model="llama3.1:8b")chain = ({"context": itemgetter("question") | retriever,"question": itemgetter("question"),"language": itemgetter("language"),}| prompt| model| StrOutputParser()
)result = chain.invoke({"question": "where did harrison work?", "language": "Chinese"})
print(result)

输出如下:

伦敦

三、LCEL下核心组件(Prompt+LLM)的实现

基本构成:PromptTemplate / ChatPromptTemplate -> LLM / ChatModel -> OutputParser

3.1 单链结构

(1)一个简单的样例

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAIprompt = ChatPromptTemplate.from_template("给我讲一个关于{topic}的笑话")
model = ChatOpenAI(temperature=0,model="gpt-3.5-turbo",
)chain = prompt | model
print(chain.invoke({"topic": "狗熊"}))

输出如下:

有一只狗熊想去参加聚会,但他不知道自己应该穿什么衣服。于是,他问了邻居老猫:“喂,我要去参加聚会了,哪种服装比较适合呢?”老猫一脸严肃地说:“我不清楚,但是你最好不要穿那件黄色的衬衣,因为它太显眼了。”

(2)自定义停止输出符

# 自定义停止输出符为\n
chain = prompt | model.bind(stop=["\n"])
print(chain.invoke({"topic": "狗熊"}))

按照上述代码,输出在遇到换行符\n时就会停止输出。

【.bind 函数介绍】,来自官网:https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.passthrough.RunnablePassthrough.html

  • Bind arguments to a Runnable, returning a new Runnable. Useful when a Runnable in a chain requires an argument that is not in the output of the previous Runnable or included in the user input…
  • 翻译一下:将参数绑定到Runnable,返回一个新的Runnable。当链中的Runnable需要一个不在前一个Runnable的输出中或包含在用户输入中的参数时,这很有用。

(3)兼容OpenAI函数调用形式

functions = [{"name": "joke","description": "讲笑话","parameters": {"type": "object","properties": {"setup": {"type": "string", "description": "笑话的开头"},"punchline": {"type": "string","description": "爆梗的结尾",},},"required": ["setup", "punchline"],},}
]chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions)
chain.invoke({"topic": "西瓜"})

(4)输出解析器

StrOutputParser :使用 StrOutputParser 输出解析器后,输出为 str 格式。

from langchain_core.output_parsers import StrOutputParserchain = prompt | model | StrOutputParser()
print(chain.invoke({"topic": "狗熊"}))

【StrOutputParser 介绍】,来自官网:https://python.langchain.com/api_reference/core/output_parsers/langchain_core.output_parsers.string.StrOutputParser.html

  • OutputParser that parses LLMResult into the top likely string.
  • 翻译一下:OutputParser将LLMResult解析为字符串的形式。

(5)与函数调用混合使用

from langchain.output_parsers.openai_functions import JsonOutputFunctionsParserchain = (prompt| model.bind(function_call={"name": "joke"})| JsonOutputFunctionsParser(key_name="setup")
)print(chain.invoke({"topic": "狗熊"}))

这里,用 JsonOutputParser输出解析器后,输出为 json 格式。其中,key_name 可以指定输出的字段。

JsonOutputParser:Parse the output of an LLM call to a JSON object.

3.2 使用Runnables来连接多链结构

3.2.1 连接多链

from operator import itemgetter  # 获取可迭代对象中指定索引或键对应的元素
from langchain.schema import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaLLMprompt1 = ChatPromptTemplate.from_template("{person}来自于哪个城市?")
prompt2 = ChatPromptTemplate.from_template("{city}属于哪个省?用{language}来回答"
)model = OllamaLLM(model="llama3.1:8b")chain1 = prompt1 | model | StrOutputParser()chain2 = ({"city": chain1, "language": itemgetter("language")}  # 获取invoke中的language| prompt2| model| StrOutputParser()
)

我们先来看看 chain1 的输出:

result = chain1.invoke({"person": "马化腾"})
print(result)
马化腾来自深圳。

chain1的输出会被当成chain2的输入,最后得到 chain2 的输出:

result = chain2.invoke({"person": "马化腾", "language": "中文"})
print(result)
马化腾来自于中国广东省深圳市。属于广东省。

3.2.2 多链执行与结果合并

用户的输入会在多个分支分别处理,最后合并结果。

唯物辩证链,给出示例代码:

from operator import itemgetter  # 获取可迭代对象中指定索引或键对应的元素
from langchain.schema import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_ollama import OllamaLLMmodel = OllamaLLM(model="llama3.1:8b")planner = (ChatPromptTemplate.from_template("生成一个关于{input}的论点")| model| StrOutputParser()| {"base_response": RunnablePassthrough()}
)arguments_for = (ChatPromptTemplate.from_template("列出以下内容的优点或积极方面: {base_response}")| model| StrOutputParser()
)arguments_against = (ChatPromptTemplate.from_template("列出以下内容的缺点或消极方面: {base_response}")| model| StrOutputParser()
)final_responder = (ChatPromptTemplate.from_messages([("ai", "{original_response}"),("human", "积极:\n{results_1}\n\n消极:\n{results_2}"),("system", "根据评论生成最终的回复"),])| model| StrOutputParser()
)chain = (planner| {"results_1": arguments_for,"results_2": arguments_against,"original_response": itemgetter("base_response"),}| final_responder
)print(chain.invoke({"input": "生孩子"}))

输出如下:

女性生育孩子是一项艰难但美好的经历。她们承担着创造生命和将其带养大的责任,这需要付出巨大努力和牺牲,但也带来深厚的母爱感激和成就感。女士,作为一个母亲,您一定会有很多不同的体验。但是,无论您是否在育儿中遇到挑战或困难,都应该庆幸自己有了孩子。因为生育孩子不仅给您带来了爱、责任和快乐,也让您有机会培养孩子,并为他们提供安全的家庭环境。当然,育儿也会带来一些不容易改变的负担,如身体疼痛、情绪波动、生活方式的改变等。然而,您也可以从育儿中体验到成就感和责任感,不仅是为您的孩子提供照顾,还有通过育儿来发现自己的能力和潜力。最终,女性生育孩子是一项充满挑战和责任的经历,但也是一个带来深厚母爱感激和成就感的机会。

用户的输入会在多个分支分别处理,最后合并结果。

3.2.3 查询SQL

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParserfrom langchain_community.utilities import SQLDatabasetemplate = """Based on the table schema below, write a SQL query that would answer the user's question:
{schema}Question: 
"""prompt = ChatPromptTemplate.from_template(template)db = SQLDatabase.from_uri("sqlite:///Chinook.db")model = ChatOpenAI(model="gpt-4",temperature=0,
)def get_schema(_):return db.get_table_info()sql_response = (RunnablePassthrough.assign(schema=get_schema)| prompt| model.bind(stop=["\nSQLResult:"])| StrOutputParser()
)sql_response.invoke({"question": "How many artists are there?"})

输出如下:

SELECT COUNT(*) FROM Artist;

可以看到上面示例中输出的是 SQL 查询语句,并没有给出自然语言的结果。下面我们将代码进行一个简单的改造:

template = """Based on the table schema below, write a SQL query that would answer the user's question:
{schema}Question: {question}
SQL Query: {query}
SQL Response: {response}
"""prompt_response = ChatPromptTemplate.from_template(template)
full_chain = (RunnablePassthrough.assign(query=sql_response).assign(schema=get_schema,response=lambda x: db.run(x["query"]),)| prompt_response| model
)
full_chain.invoke({"question": "How many artists are there?"})

输出如下:

There are 275 artists.

3.3 自定义输出解析器

Python编程助手,此处省略。感兴趣的同学可以查看原资料。

四、LCEL添加Memory

4.1 短时记忆

  • 基于 ConversationBufferMemory
from operator import itemgetter
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAImodel = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages([("system", "你是一个乐于助人的机器人"),MessagesPlaceholder(variable_name="history"),("human", "{input}"),]
)memory = ConversationBufferMemory(return_messages=True)chain = (RunnablePassthrough.assign(history=RunnableLambda(memory.load_memory_variables) | itemgetter("history"))| prompt| model
)inputs = {"input": "你好我是Mary"}
response = chain.invoke(inputs)# 保存记忆
memory.save_context(inputs, {'output': response.content})
memory.load_memory_variables({})

4.2 长时记忆

  • 基于 Redis
from langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_community.chat_models import ChatOpenAI
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory# 基于Redis保存记忆
prompt = ChatPromptTemplate.from_messages([("system", "你是一个擅长{ability}的助手"),MessagesPlaceholder(variable_name="history"),("human", "{question}"),]
)chain = prompt | ChatOpenAI(model="gpt-4-1106-preview", temperature=0)chain_with_history = RunnableWithMessageHistory(chain,# 使用redis存储聊天记录lambda session_id: RedisChatMessageHistory(session_id, url="redis://localhost:6397/0"),input_messages_key="question",history_messages_key="history",
)# 每次调用都会保存聊天记录,需要有对应的session_id
chain_with_history.invoke({"ability": "历史", "question": "中国建都时间最长的城市是哪个?"},config={"configurable": {"session_id": "Mary"}}
)

这里,我们使用了RunnableWithMessageHistory 实现了基于Redis 实现Memory的长时记忆。

五、LCEL:Agent核心组件

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.1 第一个Agent

使用 create_openai_functions_agent 函数直接定义一个简单的 OpenAI 风格的agent,示例代码:

from langchain_openai import ChatOpenAI
from langchain import hub
from langchain.agents import load_tools
from langchain.agents import create_openai_functions_agent  # 不同的agent有不同的创建方式
from langchain.agents import AgentExecutor# 创建LLM
llm = ChatOpenAI(model_name="gpt-4", temperature=0)# 定义agent的prompt
# https://smith.langchain.com/hub/hwchase17/openai-functions-agent
prompt = hub.pull("hwchase17/openai-functions-agent")# 定义工具,加载预制的工具,注意有的工具需要提供LLM
tools = load_tools(["llm-math"], llm=llm)# 创建agent
agent = create_openai_functions_agent(llm, tools, prompt)# 定义agent的执行器,这里注意与老版本的不同
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)agent_executor.invoke({"input": "你好"})

5.2 Agent案例2

实现如下功能:

  • 中间步骤处理
  • 提示词
  • 模型配置(停止符必要的话)
  • 输出解析器
from langchain import hub
from langchain.agents import AgentExecutor, tool
from langchain.agents.output_parsers import XMLAgentOutputParser
from langchain_openai import ChatOpenAI# 配置模型
model = ChatOpenAI(model="gpt-4-1106-preview",temperature=0,
)# 使用工具
@tool
def search(query: str) -> str:""" 当需要了解最新的天气的时候,才会使用这个工具。 """return "晴朗, 32摄氏度, 无风"tool_list = [search]# 提示词模板
# https://smith.langchain.com/hub
# Get the prompt to use - you can modify this!
prompt = hub.pull("hwchase17/xml-agent-convo")def convert_intermediate_steps(intermediate_steps):log = ""for action, observation in intermediate_steps:log += (f"<tool>{action.tool}</tool><tool_input>{action.tool_input}"f"></tool_input><observation>{observation}</observation>")return log# 将工具列表插入模板中
def convert_tools(tools):return "\n".join([f"{tool.name}: {tool.description}" for tool in tools])# 定义agent
agent = ({"input": lambda x: x["input"],"agent_scratchpad": lambda x: convert_intermediate_steps(x["intermediate_steps"])},prompt.partial(tools=convert_tools(tool_list)),model.bind(stop=["</tool_input>", "</final_answer>"]),XMLAgentOutputParser()
)# 执行agent
agent_executor = AgentExecutor(agent=agent, tools=tool_list, verbose=True)
result = agent_executor.invoke({"input": "北京今天的天气如何?"})
print(result)

相关文章:

【LangChain】理论及应用实战(7):LCEL

文章目录 一、LCEL简介二、LCEL示例2.1 一个简单的示例2.2 RAG Search 三、LCEL下核心组件&#xff08;PromptLLM&#xff09;的实现3.1 单链结构3.2 使用Runnables来连接多链结构3.2.1 连接多链3.2.2 多链执行与结果合并3.2.3 查询SQL 3.3 自定义输出解析器 四、LCEL添加Memor…...

Leetcode 刷题笔记1 单调栈part02

leetcode 42 接雨水 本题用双指针法更为浅显易懂 双指针法&#xff1a; class Solution:def trap(self, height: List[int]) -> int:leftheight, rightheight [0] * len(height), [0] * len(height)ans 0leftheight[0] height[0]for i in range(1, len(height)):lefth…...

ai本地化 部署常用Ollama软件

现在用最简单的方式介绍一下 Ollama 的作用和用法&#xff1a; Ollama 是什么&#xff1f; Ollama 是一个让你能在自己电脑上免费运行大型语言模型&#xff08;比如 Llama 3、Mistral 等&#xff09;的工具。 相当于你本地电脑上有一个类似 ChatGPT 的 AI&#xff0c;但完全…...

vllm部署QwQ32B(Q4_K_M)

vllm部署QwQ32B(Q4_K_M) Ollama是一个轻量级的开源LLM推理框架&#xff0c;注重简单易用和本地部署&#xff0c;而VLLM是一个专注于高效推理的开源大型语言模型推理引擎&#xff0c;适合开发者在实际应用中集成和使用。两者的主要区别在于Ollama更注重为用户提供多种模型选择和…...

VLLM:虚拟大型语言模型(Virtual Large Language Model)

VLLM&#xff1a;虚拟大型语言模型&#xff08;Virtual Large Language Model&#xff09; VLLM指的是一种基于云计算的大型语言模型的虚拟实现。它通常是指那些由多个服务器组成的分布式计算环境中的复杂机器学习模型&#xff0c;这些模型能够处理和理解大量的文本数据。VLLM的…...

企业内网监控软件的选型与应用:四款主流产品的深度剖析

在数字化办公的时代背景下&#xff0c;企业内部网络管理的重要性愈发显著。对于企业管理者而言&#xff0c;如何精准掌握员工工作状态&#xff0c;保障网络安全与工作效率&#xff0c;已成为亟待解决的关键问题。本文将深入剖析四款主流企业内网监控软件&#xff0c;探讨其功能…...

蓝桥杯省赛(2024)

问题描述 小蓝和朋友们在玩一个报数游戏。由于今年是 20242024 年&#xff0c;他们决定要从小到大轮流报出是 2020 或 2424 倍数的正整数。前 1010 个被报出的数是&#xff1a;20,24,40,48,60,72,80,96,100,12020,24,40,48,60,72,80,96,100,120。请问第 2024202420242024202420…...

Qt窗口控件之字体对话框QFontDialog

字体对话框QFontDialog QFontDialog 是 Qt 内置的字体对话框&#xff0c;用户能够在这里选择字体的样式、大小&#xff0c;设置加粗和下划线并将结果作为返回值返回。QFontDialog 最好使用其提供的静态函数实例化匿名对象&#xff0c;并获取返回值最为用户选择字体设置的结果。…...

Qt QML实现视频帧提取

## 前言 视频帧率&#xff08;Frame Rate&#xff09;是指视频播放时每秒显示的画面帧数&#xff0c;通常用fps&#xff08;Frames Per Second&#xff09;来表示。视频是由一系列静止的图像帧组成的&#xff0c;而视频帧率则决定了这些图像帧在单位时间内播放的速度。较高的视…...

网络性能指标

目录 时延 延迟抖动 丢包率 时延&#xff1a;数据传输的快慢&#xff0c;影响实时性。抖动&#xff1a;延迟的变化&#xff0c;影响稳定性。丢包率&#xff1a;数据丢失的比例&#xff0c;影响可靠性。 时延 定义&#xff1a;时延是指数据从发送端传输到接收端所需的时间&…...

在 Ubuntu 服务器上使用宝塔面板搭建博客

&#x1f4cc; 介绍 在本教程中&#xff0c;我们将介绍如何在 Ubuntu 服务器 上安装 宝塔面板&#xff0c;并使用 Nginx PHP MySQL 搭建一个博客&#xff08;如 WordPress&#xff09;。 主要步骤包括&#xff1a; 安装宝塔面板配置 Nginx PHP MySQL绑定域名与 SSL 证书…...

计算机组成与接口16

1.0的表示方法唯一的有补码&#xff0c;移码&#xff0c;ASCII码 2.可以多次编程的只读存储器是EPROM,掩膜式ROM 3.8259A芯片可设置成脉冲边沿触发方式&#xff1b;全嵌套方式&#xff1b;自动中断结束方式&#xff1b;特殊屏蔽方式 4.计算机系统中的总线按层次可以分为板级…...

有了大语言模型还需要 RAG 做什么

一、百炼平台简介 阿里云的百炼平台就像是一个超级智能的大厨房&#xff0c;专门为那些想要做出美味AI大餐的企业和个人厨师准备的。你不需要从头开始做每一道菜&#xff0c;因为这个厨房已经为你准备了很多预制食材&#xff08;预训练模型&#xff09;&#xff0c;你可以根据…...

【从0到1搞懂大模型】RNN基础(4)

先说几个常用的可以下载数据集的地方 平台&#xff1a;kaggle&#xff08;https://www.kaggle.com/datasets&#xff09; 和鲸社区&#xff08;https://www.heywhale.com/home&#xff09; 阿里天池&#xff08;https://tianchi.aliyun.com/&#xff09; 其他&#xff1a;海量公…...

【第K小数——可持久化权值线段树】

题目 代码 #include <bits/stdc.h> using namespace std;const int N 1e5 10;int a[N], b[N]; int n, m, len; int rt[N], idx; // idx 是点分配器struct node {int l, r;int s; } tr[N * 22];int getw(int x) {return lower_bound(b 1, b len 1, x) - b; }int bui…...

直流减速电机控制实验:Simulink应用层开发(1)

文章目录 1 阶段目标2 功能需求3 需求拆解及方案研究3.1 需求拆解3.2 按键指令识别3.3 电机状态转换3.4 脉宽及启停判断4 总结1 阶段目标 本文是《直流减速电机控制实验》的第三部分,会通过图文结合的方式,手把手带读者操作Simulink工具进行直流减速电机的应用层开发。 本章…...

本地部署Deep Seek-R1,搭建个人知识库——笔记

目录 一、本地部署 DeepSeek - R1 1&#xff1a;安装Ollama 2&#xff1a;部署DeepSeek - R1模型 3&#xff1a;安装Cherry Studio 二、构建私有知识库 一、本地部署 DeepSeek - R1 1&#xff1a;安装Ollama 1.打开Ollama下载安装 未科学上网&#xff0c;I 先打开迅雷再下…...

【软考-架构】5.3、IPv6-网络规划-网络存储-补充考点

✨资料&文章更新✨ GitHub地址&#xff1a;https://github.com/tyronczt/system_architect 文章目录 IPv6网络规划与设计建筑物综合布线系统PDS&#x1f4af;考试真题第一题第二题 磁盘冗余阵列网络存储技术其他考点&#x1f4af;考试真题第一题第二题 IPv6 网络规划与设计…...

fastapi+angular外卖系统

说明&#xff1a; fastapiangular外卖系统 1.美食分类&#xff08;粥&#xff0c;粉&#xff0c;面&#xff0c;炸鸡&#xff0c;炒菜&#xff0c;西餐&#xff0c;奶茶等等&#xff09; 2.商家列表 &#xff08;kfc&#xff0c;兰州拉面&#xff0c;湘菜馆&#xff0c;早餐店…...

Oracle静默安装方法

Web服务器上面的Linux一般是不会有图形界面的&#xff0c;所有通过图形界面来安装Linux的方式在没有图形界面的Linux上面是行不通的&#xff0c;我们要使用的安装方式叫做Linux的静默安装。即在没有图形界面的Linux上面安装。 1. 下载地址 http://www.oracle.com/technetwork…...

鸿蒙路由 HMRouter 配置及使用 三 全局拦截器使用

1、前期准备 简单封装一个用户首选项的工具类 import { preferences } from "kit.ArkData";// 用户首选项方法封装 export class Preferences {private myPreferences: preferences.Preferences | null null;// 初始化init(context: Context, options: preference…...

计算机视觉——深入理解卷积神经网络与使用卷积神经网络创建图像分类算法

引言 卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;简称 CNNs&#xff09;是一种深度学习架构&#xff0c;专门用于处理具有网格结构的数据&#xff0c;如图像、视频等。它们在计算机视觉领域取得了巨大成功&#xff0c;成为图像分类、目标检测、图像分…...

永磁同步电机无速度算法--拓展卡尔曼滤波器

一、原理介绍 以扩展卡尔曼滤波算法为基础&#xff0c;建立基于EKF算法的估算转子位置和转速的离散模型。 实时性是扩展卡尔曼滤波器的一种特征&#xff0c;所以它可实时跟踪系统的状态并进行有效的输出&#xff0c;同时&#xff0c;它可以减少干扰、抑制噪声&#xff0c;其效…...

电机控制常见面试问题(十五)

文章目录 一、电机气隙二、电气时间三.电机三环控制详解四.驱动板跳线意义 一、电机气隙 电机气隙是定子和转子之间的空隙&#xff0c;防止钉子转子运转时物理接触&#xff0c;此外&#xff0c;气隙是磁路的重要环节&#xff0c;磁场需通过气隙传递能量&#xff0c;但其较高的…...

a2字幕分享

1. 沟通communication Hey everybody Welcome to this A2 English listening practice video. You can use this video to practice your listening and comprehension as I speak. Before we start, remember to download the Listening Time podcast and become a member a…...

基于cat1的多传感器融合的贵重资产管理解决方案项目说明书

一、产品需求 在物流运输中&#xff0c;搭载 Cat 1 模块的贵重货物跟踪设备&#xff0c;可将货物的位置、震动、温湿度等数据及时传输给物流调度中心&#xff0c;以便及时应对运输途中可能出现的问题&#xff0c;如路线偏离、货物受损风险等 。而且&#xff0c;Cat 1 依托成熟的…...

deepseek使用记录23——我们的遭遇

世界观设定 时间&#xff1a;近未来2035年&#xff0c;全球进入"数字绩效社会"地点&#xff1a;重庆赛博朋克风格的"云端之城"&#xff0c;外卖骑手被称为"数据蜂鸟"核心科技&#xff1a;情感区块链系统&#xff0c;人类情绪波动可转化为能量币…...

【CF】Day9——Codeforces Round 953 (Div. 2) BCD

B. New Bakery 题目&#xff1a; 思路&#xff1a; 被标签害了&#xff0c;用什么二分&#xff08; 很简单的思维题&#xff0c;首先如果a > b&#xff0c;那么全选a就行了&#xff0c;还搞啥活动 否则就选 b - a 天来搞活动&#xff0c;为什么&#xff1f; 首先如果我…...

PEFT简介

以下是关于 PEFT&#xff08;Parameter-Efficient Fine-tuning&#xff09; 的简介&#xff0c;涵盖其定义、核心思想、常见方法及应用场景&#xff1a; 1. 什么是PEFT&#xff1f; PEFT&#xff08;参数高效微调&#xff09;是机器学习领域的一种技术&#xff0c;专为预训练大…...

harmonyOS NEXT开发与前端开发深度对比分析

文章目录 1. 技术体系概览1.1 技术栈对比1.2 生态对比 2. 开发范式比较2.1 鸿蒙开发范式2.2 前端开发范式 3. 框架特性对比3.1 鸿蒙 Next 框架特性3.2 前端框架特性 4. 性能优化对比4.1 鸿蒙性能优化4.2 前端性能优化 5. 开发工具对比5.1 鸿蒙开发工具5.2 前端开发工具 6. 学习…...