06|LangChain | 从入门到实战 -六大组件之Agent

点点赞~

注意:langchain的版本迭代比较快,社区维护,代码当中或许部分方法在某个版本不再支持

01|LangChain | 从入门到实战-介绍
02|LangChain | 从入门到实战 -六大组件之Models IO
03|LangChain | 从入门到实战 -六大组件之Retrival
04|LangChain | 从入门到实战 -六大组件之Chain
05|LangChain | 从入门到实战 -六大组件之Memory

一、代理原理

代理的核心思想是使用语言模型来选择一系列操作。在链中,一系列操作是硬编码的。在代理中,语言模型被用作推理引擎来确定要采取哪些操作以及按什么顺序。
需要了解的重要概念:

需要了解的重要概念:

  • AgentAction:表示代理应采取的操作。它有一个 tool 属性(要调用的工具的名称)和一个 tool_input 属性(该工具的输入)
  • AgentFinish:表示代理已完成,应返回给用户。它有一个 return_values 参数,它通常只有一个键—— output,即一个字符串,因此通常只返回这个键。
  • intermediate_steps:代表之前的代理操作和相应输出。这对于传递给未来迭代非常重要,所以代理知道它已经完成了哪些工作。它被编码为List[Tuple[AgentAction, Any]].

总的来说,代理的核心思想是:

  • 使用语言模型来选择一系列操作
  • AgentAction 表示一个操作 [] (messagelog)
  • AgentFinish 表示代理已完成 [AgentFinish(return_values={‘output’: ‘单词"color"有5个字母。’}, log=‘单词"color"有5个字母。’)]
  • intermediate_steps 记录之前的操作和输出,用于未来迭代【tool3 ,tools2,tools3】

语言模型作为推理引擎,确定要采取哪些操作和按什么顺序。

Agent(代理):在 Langchain 中,Agent 是指一个智能合约的实例。它代表了合约的执行者,可以看作是一个具有特定功能的智能合约的化身。Agent 能够根据合约的逻辑执行相应的操作,如转账、查询余额等。它是区块链网络中的一个基本单位,可以理解为一个可编程的、自主执行任务的角色。

Chain(链):Langchain 中的 Chain 指的是一个由多个 Agent 组成的序列。这些 Agent 按照一定的顺序链接在一起,形成一个链式结构。Chain 是 Langchain 平台的基本组织结构,用于实现分布式账本、智能合约等功能。每个 Chain 都对应一个唯一的标识符,如一个哈希值。Chain 中的 Agent 按照预先设定的规则执行任务,共同维护整个链的稳定和安全。

Agent 是 Chain 的基本组成单元,一个 Chain 由多个 Agent 构成。

Chain 是 Agent 存在的载体,Agent 通过加入 Chain 来实现其功能和价值。

Agent 和 Chain 共同构成了 Langchain 平台的核心技术体系

1、源码查看

https://github.com/langchain-ai/langchain/blob/804390ba4bcc306b90cb6d75b7f01a4231ab6463/libs/langchain/langchain/agents/init.py

在这里插入图片描述

2、创建工具 (装饰器方法)

from langchain.chat_models import ChatOpenAI
# 创建语言模型
llm = ChatOpenAI(temperature=0)

# 构建工具
from langchain.agents import tool
@tool
def get_word_length(word: str) -> int:
    """返回单词的长度"""
    return len(word)
# 创建工具清单
tools = [get_word_length]

看看工具函数
一个name参数,代表这个函数名称
一个description,返回这个工具的使用说明

在这里插入图片描述

3、绑定工具

# 绑定工具
from langchain.tools.render import format_tool_to_openai_function # 格式化函数作为符合openai格式的描述体
llm_with_tools = llm.bind(
    functions=[format_tool_to_openai_function(t) for t in tools]
)

format_tool_to_openai_function 这个方法将工具函数,转换为符合 OpenAi格式的描述体,即 fucntion calling

函数调用是构建由 LLM 驱动的聊天机器人或代理的一项重要功能,这些聊天机器人或代理需要检索 LLM 的上下文或通过将自然语言转换为 API 调用来与外部工具交互。

参考文章:https://mychen76.medium.com/state-of-function-calling-in-llm-bc3aa37decb4

在这里插入图片描述

4、创建代理

下面代码,一个是prompt,创建了2个输入key

  • input 用于用户输入内容
  • agent_scratchpad 用户代理中间使用过程的记录
#  创建代理
from langchain.agents.format_scratchpad import format_to_openai_functions
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个非常优秀的人,但是不会计算单词的长度"),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"), # 消息体当中添加一个 key,记录代理的使用过程
])

agent = {
    "input": lambda x: x["input"],
    "agent_scratchpad": lambda x: format_to_openai_functions(x['intermediate_steps']) # 代理的使用过程
} | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()

现在来使用它

output = agent.invoke({
    "input": "关于color有多少个字母?",
     "intermediate_steps": [],# 中间步骤
})

可以看到生成了 一个 AgentActionMessageLog ,这个表示代理应该要采集的动作,并没有到结束

在这里插入图片描述

为了更加直观,我复制出来
可以看到,将用户的问:“关于color有多少个字母?” 这个问题去,提取了 color,并且准备调用 get_word_length 工具函数
关键字:tooltool_input

在这里插入图片描述

现在我询问另外一个问题,看看输出的样式,直接为 AgentFinish,这个表明代理已经完成动作,原因在于,我们封装的工具函数,并没有解决 “太阳和地球的距离

关键字:return_values

在这里插入图片描述

5、完整代码

好了,到现在是不是看起来有点懵逼,现在,通过下面代码来加深一步过程

一个代理Agent,从白话文来说-简化成2个过程

  • AgentAction 代理开始
  • AgentFinish 代理结束,当只有看到这个类型才视为结束

那么现在,将前面的代码抽取出来,通过while True 完善 工具链的使用

from langchain.chat_models import ChatOpenAI
# 创建语言模型
llm = ChatOpenAI(temperature=0)

# 构建工具
from langchain.agents import tool
@tool
def get_word_length(word: str) -> int:
    """返回单词的长度"""
    return len(word)
# 创建工具清单
tools = [get_word_length]

# 绑定工具
from langchain.tools.render import format_tool_to_openai_function # 格式化函数作为符合openai格式的描述体
llm_with_tools = llm.bind(
    functions=[format_tool_to_openai_function(t) for t in tools]
)
#  创建代理
from langchain.agents.format_scratchpad import format_to_openai_functions
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个非常优秀的人,但是不会计算单词的长度"),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"), # 消息体当中添加一个 key,记录代理的使用过程
])

agent = {
    "input": lambda x: x["input"],
    "agent_scratchpad": lambda x: format_to_openai_functions(x['intermediate_steps']) # 代理的使用过程
} | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()


from langchain.schema.agent import AgentFinish
intermediate_steps = []
count = 1 
while True:
    
    output = agent.invoke({
        "input": "关于color有多少个字母?",
        "intermediate_steps": intermediate_steps
    })
    print(f'\n轮询第{count}次',output,'过程对象:',type(output))
    count +=1 
    
    # 判断代理是否有结束标记,有的话结束
    if isinstance(output, AgentFinish):
        final_result = output.return_values["output"]
        break
    else:
        # 从AgentAction 中提取要执行的 tool(工具名称),跟tool_input(工具的输入参数)
        tool = {
            "get_word_length": get_word_length
        }[output.tool]
        observation = tool.run(output.tool_input)  # 运行工具函数,并且得到结果
        intermediate_steps.append((output, observation))

查看结果,可以看到出来了回复

在这里插入图片描述

6、简化代码

前面的代码,更多的是为了让大家了解底层原理,langchain提供了一个函数,用于简化操作。

from langchain.chat_models import ChatOpenAI
# 创建语言模型
llm = ChatOpenAI(temperature=0)

# 构建工具
from langchain.agents import tool
@tool
def get_word_length(word: str) -> int:
    """返回单词的长度"""
    return len(word)
# 创建工具清单
tools = [get_word_length]

# 绑定工具
from langchain.tools.render import format_tool_to_openai_function # 格式化函数作为符合openai格式的描述体
llm_with_tools = llm.bind(
    functions=[format_tool_to_openai_function(t) for t in tools]
)

#  创建代理
from langchain.agents.format_scratchpad import format_to_openai_functions
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个非常优秀的人,但是不会计算单词的长度"),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"), # 消息体当中添加一个 key,记录代理的使用过程
])

agent = {
    "input": lambda x: x["input"],
    "agent_scratchpad": lambda x: format_to_openai_functions(x['intermediate_steps']) # 代理的使用过程
} | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()

# 使用代理
from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor.invoke({"input": "关于color有多少个字母?"})

看看结果:
在这里插入图片描述

关于 AgentExecutor 这个方法常用参数说明

  • max_iterations 默认迭代工具15次,可以设置
  • return_intermediate_steps 是否返回代理的中间步骤轨迹在最后除了最终输出之外

关于 AgentExecutor 的源码
https://github.com/langchain-ai/langchain/blob/804390ba4bcc306b90cb6d75b7f01a4231ab6463/libs/langchain/langchain/agents/agent.py#L917

在这里插入图片描述

7、加上历史对话

为了做到这一点,需要添加内存来解决这个问题:

1、在提升中添加内存变量的位置

2、跟踪聊天记录

首先在提示中添加一个内存位置。通常使用带有key的消息添加占位符来实现此目的的“chat_history”
这个放入的位置是有讲究,放到新用户输入的之上(符合对话流程) MessagesPlaceholder 注意看 prompt 该位置

from langchain.agents.format_scratchpad import format_to_openai_functions
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.prompts import MessagesPlaceholder, ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.agents import tool, AgentExecutor
from langchain.tools.render import format_tool_to_openai_function

# 创建语言模型
llm = ChatOpenAI(temperature=0)


# 构建工具
@tool
def get_word_length(word: str) -> int:
    """返回单词的长度"""
    return len(word)
tools = [get_word_length]


# 绑定工具
llm_with_tools = llm.bind(
    functions=[format_tool_to_openai_function(t) for t in tools]
)

MEMORY_KEY = "chat_history"
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个非常优秀的人,但是不会计算单词的长度"),
    MessagesPlaceholder(variable_name=MEMORY_KEY),
    ("user", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])


chat_history = []

agent = {
    "input": lambda x: x["input"],
    "agent_scratchpad": lambda x: format_to_openai_functions(x['intermediate_steps']),
    "chat_history": lambda x: x["chat_history"]
} | prompt | llm_with_tools | OpenAIFunctionsAgentOutputParser()
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 模拟已经对话过一次
input1 = "关于color有多少个字母?"
result = agent_executor.invoke({"input": input1, "chat_history": chat_history})

 # 历史消息加上聊天记录
chat_history.append(HumanMessage(content=input1))
chat_history.append(AIMessage(content=result['output']))

agent_executor.invoke({"input": "这个单词中文翻译是什么?", "chat_history": chat_history})

可以看到执行了2次

在这里插入图片描述

二、Agent使用

在开始下面之前,以1,2 小节知识作为更好理解代理,Agent,既可以看到成tool工具,chain链,等等

1、langchain-smith 介绍

在开始之前,先了解一下 langchain - smith 上提供的 hub 平台,当然这个平台还有其它功能,比如测试应用的流等等

https://smith.langchain.com/hub

其中这个平台提供了很多 prompt 的用例,我们可以通过代码拉取现成的prompt 在langchain中使用
在这里插入图片描述

我们来看一下这个 prompt

https://smith.langchain.com/hub/hwchase17/react-chat?organizationId=be7e61a9-df79-5253-909f-e90160a9f410

在这里插入图片描述

2、ReAct 介绍

强烈建议大家去看看这篇文章

https://react-lm.github.io/

以及这篇论文:https://arxiv.org/pdf/2210.03629.pdf.

在这里插入图片描述

ReAct 是一个结合了推理和行动功能的方法,通过交叉生成推理轨迹和特定于任务的动作,从而实现更大的协同作用。它在问答和决策任务中表现优秀,具有较高的可解释性和可信度。通过人类对齐的 ReAct 提示设计,使得模型能够更好地理解和应用人类思维的模式,取得了令人印象深刻的结果。虽然还存在改进的空间,但ReAct 在许多任务上展示出了很高的潜力和有效性。

在这里插入图片描述

关键词记忆:

  1. Action 行动
  2. Thought 思考做出何种决策
  3. Observation 观察决策的结果
  4. Answer 回复总结答案
  5. Finish 结束推理决策

当然,这是一种prompt的写法,能够很好的提升对于交互问题,另外还有,COT、TOT等架构,如果想了解更多promtp等使用,可以阅读下面网站

https://www.promptingguide.ai/research
在这里插入图片描述

3、使用内置工具

在本案例中,通过内置工具调用,并且利用langchain-smith 中 hub 的prompt ,将工具绑定进去使用

from langchain.tools import YouTubeSearchTool,Tool
tool = YouTubeSearchTool()
tool.run("成龙")

可以看到,能够出来2个url,此时打开网页查询一下

请添加图片描述

利用partial,格式化部分模版的参数,这里将hub模版拉下来,指定2个参数添加内容(这个模版有5个参数,这里只要2个使用)
https://github.com/langchain-ai/langchain/blob/804390ba4bcc306b90cb6d75b7f01a4231ab6463/libs/core/langchain_core/prompts/base.py#L181
在这里插入图片描述
如果用format_prompt 则需要指定额外参数才行,可以看源码,或者自己体验,只传2个参数会出错

from langchain.tools import YouTubeSearchTool,Tool
tool = YouTubeSearchTool()
# 创建工具
tools = [
    Tool(
        name='youtube搜索',
        func=tool.run,
        description='用户如果问题有关成龙则使用这个工具'
    )
]
# 在prompt中绑定工具
from langchain.tools.render import render_text_description 
source_prompt = hub.pull("hwchase17/react-chat")
prompt = source_prompt.partial(
    tools=render_text_description(tools),# 返回工具的文本描述
    tool_names=", ".join([t.name for t in tools]),
)
# 绑定工具
from langchain.llms import OpenAI
llm = OpenAI(temperature=0)
llm_with_stop = llm.bind(stop=["\nObservation"]) # 参考ReAct架构,添加一个停止词

# 创建代理,可以看到这里对于模版剩下3个提示词,进行了操作,
from langchain.agents.output_parsers import ReActSingleInputOutputParser
from langchain.agents.format_scratchpad import format_log_to_str
agent = {
            "input": lambda x: x["input"],# 用户输入
            "agent_scratchpad": lambda x: format_log_to_str(x['intermediate_steps']),# 一个是代理执行步骤
            "chat_history": lambda x: x["chat_history"] # 聊天记录
        } | prompt | llm_with_stop | ReActSingleInputOutputParser()

# 创建代理执行执行器
from langchain.agents import AgentExecutor
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="chat_history")
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, memory=memory)

看看结果,2轮对话

在这里插入图片描述

4、AgentType

在前面,我们看到了工具创建好了,都通过自己创建Agent进行,使用,现在我们可以通过现成的封装直接使用,关于更多功能

查看源代码
在这里插入图片描述

准备工作,去这个平台注册一个key
https://serpapi.com/manage-api-key
在这里插入图片描述

安装一个包

pip install google-search-results
from langchain.agents import Tool
from langchain.agents import AgentType
from langchain.memory import ConversationBufferMemory
from langchain.llms import OpenAI
from langchain.utilities import SerpAPIWrapper
from langchain.agents import initialize_agent
import os 
os.environ["SERPAPI_API_KEY"] = ""
search = SerpAPIWrapper()
tools = [
    Tool(
        name='物流工具',
        func=search.run,
        description='这对于回答相关船期与货物跟踪的时候非常有用,如果计算问题不要使用这个工具'
    )
]
llm = OpenAI(temperature=0)
memory = ConversationBufferMemory(memory_key="chat_history")

# 使用现成的代理类创建代理
agent_executor = initialize_agent(
    tools,
    llm,
    agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
    verbose=True,
    memory=memory,
)

关于 AgentType.CONVERSATIONAL_REACT_DESCRIPTION

执行一下看看结果

agent_executor.invoke({'盐田到洛杉矶会经过哪些港口'})

在这里插入图片描述

5、多工具组合以及AgentExecutorIterator使用

AgentExecutorIterator 在 langchain 中主要用于:

  1. 批量执行代理 AgentExecutorIterator 可以将一组输入数据,批量传递给代理,并获取代理的批量输出。
  2. 迭代执行代理 AgentExecutorIterator 可以迭代执行代理,每次传递一个输入,获取一个输出。
  3. 提供进度提示 AgentExecutorIterator 可以提供进度提示,显示当前执行到第几个输入。

step1:创建模型跟链

from langchain.chains import LLMMathChain
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(temperature=0, model="gpt-4")
llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)

step2:创建2个工具

import pydantic.v1 as pydantic
from langchain.agents.tools import Tool
primes = {998: 7901, 999: 7907, 1000: 7919}

class CalculatorInput(pydantic.BaseModel):
    """计算器的输入"""
    question: str = pydantic.Field()
    
class PrimeInput(pydantic.BaseModel):
    """主输入"""
    n: int = pydantic.Field()
    
def is_prime(n: int) -> bool:
    if n <= 1 or (n % 2 == 0 and n > 2):
        return False
    for i in range(3, int(n ** 0.5) + 1, 2):
        if n % i == 0:
            return False
    return True

def get_prime(n: int, primes: dict = primes) -> str:
    """计算素数"""
    return str(primes.get(int(n)))

async def aget_prime(n: int, primes: dict = primes) -> str:
    """代理"""
    return str(primes.get(int(n)))

# 工具清单
tools = [
    Tool(
        name="GetPrime",
        func=get_prime,
        description="返回第 n 个素数的工具",
        args_schema=PrimeInput,  # 以pydantic 进行约束字段
        coroutine=aget_prime, # 异步
    ),
    Tool.from_function(
        func=llm_math_chain.run,
        name="Calculator",
        description="当您需要计算数学表达式时很有用",
        args_schema=CalculatorInput, # 以pydantic 进行约束字段
        coroutine=llm_math_chain.arun, # 异步
    ),
]

step3:创建代理并且使用代理

# 创建代理
agent = initialize_agent(
    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
# 使用代理
question = "第 998 个、第 999 个和第 1000 个素数的乘积是多少?"

for step in agent.iter(question):
    if output := step.get("intermediate_step"):
        action, value = output[0]
        if action.tool == "GetPrime":
            print(f"正在检查 {value} 是否为质数...")
            assert is_prime(int(value))
        # Ask user if they want to continue
        _continue = input("代理是否应该继续 (Y/n)?:\n")
        if _continue != "Y":
            break

查看结果,很有意思

1、检查用户输入的998,999,1000 通过工具 is_prime 检查是否为素数

2、然后最后得到3个素数,调用 get_prime 工具进行计算

3、整个过程当中因为使用了ReAct ,能够看到关键词
- Action
- Action input
- Observation
- Thought
- Answer
- Final Answer

4、什么时候使用另外一个工具,也做到了,这就是prompt工程的魅力

在这里插入图片描述

平替方法:

from langchain.agents import AgentExecutorIterator

AgentExecutorIterator(
    agent_executor=agent_executor,
    inputs=[{'input': "第 998 个、第 999 个和第 1000 个素数的乘积是多少?"}]
)
# 迭代执行代理,获取输出
outputs = []
for output in iterator:
    outputs.append(output)

在这里插入图片描述

6、总结

为了更好的理解Agent,langchain封装了挺多的函数

  • 对于用户输入前内容处理的函数 比如,利用 prompt
  • 对于模型与内容交互时候处理工艺的函数,比如利用 ReAct模式
  • 对于返回结果,格式化某样式的工艺函数,比如输出JSON

在这里插入图片描述

对于Agent而言,前文也做了部分解释

Agent(代理):在 Langchain 中,Agent 是指一个智能合约的实例。它代表了合约的执行者,可以看作是一个具有特定功能的智能合约的化身。Agent 能够根据合约的逻辑执行相应的操作,如转账、查询余额等。它是区块链网络中的一个基本单位,可以理解为一个可编程的、自主执行任务的角色。

Chain(链):Langchain 中的 Chain 指的是一个由多个 Agent 组成的序列。这些 Agent 按照一定的顺序链接在一起,形成一个链式结构。Chain 是 Langchain 平台的基本组织结构,用于实现分布式账本、智能合约等功能。每个 Chain 都对应一个唯一的标识符,如一个哈希值。Chain 中的 Agent 按照预先设定的规则执行任务,共同维护整个链的稳定和安全。

Agent 是 Chain 的基本组成单元,一个 Chain 由多个 Agent 构成。

Chain 是 Agent 存在的载体,Agent 通过加入 Chain 来实现其功能和价值。

Agent 和 Chain 共同构成了 Langchain 平台的核心技术体系

源码地址

https://github.com/langchain-ai/langchain/blob/804390ba4bcc306b90cb6d75b7f01a4231ab6463/libs/langchain/langchain/agents/init.py

可以看到有很多方法跟功能

在这里插入图片描述

对于部分封装函数,以案例介绍,对于详细函数的理解,建议大家看源码,比如这样

复制 create_json_agent 这个函数,在源码进行查看

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/592171.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

asp.net结课作业中遇到的问题解决2

目录 1、如何实现评论交流的界面 2、如果想要将文字添加到数据库中&#xff0c;而不是乱码&#xff0c;该怎么修改 3、如果想要添加的数据已经存在于数据库&#xff0c;就不允许添加了&#xff0c;该如何实现 4、想要实现某个模块下有好几个小的功能该如何实现 5、想要实现…

代码随想录算法训练营第25天 | 216.组合总和III、17.电话号码的字母组合

代码随想录算法训练营第25天 | 216.组合总和III、17.电话号码的字母组合 自己看到题目的第一想法看完代码随想录之后的想法 链接: 216.组合总和III 链接: 17.电话号码的字母组合 自己看到题目的第一想法 216.组合总和III&#xff1a;递归函数终止条件为搜索得到的数相加为n&…

【架构系列】RabbitMQ应用场景及在实际项目中如何搭建可靠的RabbitMQ架构体系

作者:后端小肥肠 创作不易&#xff0c;未经允许禁止转载。 1. 前言 RabbitMQ&#xff0c;作为一款高性能、可靠的消息队列软件&#xff0c;已经成为许多企业和开发团队的首选之一。它的灵活性和可扩展性使得它适用于各种应用场景&#xff0c;从简单的任务队列到复杂的分布式系统…

阿里低代码引擎学习记录

官网 一、关于设计器 1、从设计器入手进行低代码开发 设计器就是我们用拖拉拽的方法&#xff0c;配合少量代码进行页面或者应用开发的在线工具。 阿里官方提供了以下八个不同类型的设计器Demo&#xff1a; 综合场景Demo&#xff08;各项能力相对完整&#xff0c;使用Fusion…

【前端项目——分页器】手写分页器实现(JS / React)

组件介绍 用了两种方式实现&#xff0c;注释详细~ 可能代码写的不够简洁&#xff0c;见谅&#x1f641; 1. 包含内容显示的分页器 网上看了很多实现&#xff0c;很多只有分页器部分&#xff0c;没和内容显示联动。 因此我增加了模拟content的显示&#xff0c;这里模拟了32条数…

Python数据分析案例44——基于模态分解和深度学习的电负荷量预测(VMD+BiGRU+注意力)

案例背景 承接之前的案例&#xff0c;说要做模态分解加神经网络的模型的&#xff0c;前面纯神经网络的缝合模型参考数据分析案例41和数据分析案例42。 虽然我自己基于各种循环神经网络做时间序列的预测已经做烂了.....但是还是会有很多刚读研究生或者是别的领域过来的小白来问…

Monorepo(单体仓库)与MultiRepo(多仓库): Monorepo 单体仓库开发策略与实践指南

&#x1f31f; 引言 在软件开发的浩瀚宇宙里&#xff0c;选择合适的代码管理方式是构建高效开发环境的关键一步。今天&#xff0c;我们将深入探讨两大策略——Monorepo&#xff08;单体仓库&#xff09;与MultiRepo&#xff08;多仓库&#xff09;&#xff0c;并通过使用现代化…

Vue3 + Vite + TypeScript + Element-Plus创建管理系统项目

官方文档 Vue3官网 Vite官方中文文档 创建项目 使用npm命令创建项目&#xff1a; npm create vitelatest输入项目名称&#xff1a; ? Project name:项目名选择vue&#xff1a; ? Select a framework: - Use arrow-keys. Return to submit.Vanilla > VueReactPrea…

【网站项目】木里风景文化管理平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

CSS精灵图、字体图标、HTML5新增属性、界面样式和网站 favicon 图标

精灵图 为什么要使用精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度,因此&#xff0c;为了有效地减少服务…

JAVA基础|常用API-JDK8之前传统的日期,时间

一. Date &#xff08;一&#xff09;说明 代表的是日期和时间 &#xff08;二&#xff09;常用的用法 构造器说明public Date()创建一个Date对象&#xff0c;代表的是系统当前此刻日期时间public Date(long time)把时间毫秒值转换成Date日期对象 常见方法说明public long …

算法提高之潜水员

算法提高之潜水员 核心思想&#xff1a;二维01背包 两个容量v1v2注意状态计算时j和p可以<各自的v #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 1010,M 80,K 22;int f[K][M];int k,V1,V2;int main(){ci…

FloodFill-----洪水灌溉算法(DFS例题详解)

目录 一.图像渲染&#xff1a; 代码详解&#xff1a; 二.岛屿数量&#xff1a; 代码详解&#xff1a; 三.岛屿的最大面积&#xff1a; 代码详解&#xff1a; 四.被围绕的区域&#xff1a; 代码详解&#xff1a; 五.太平洋大西洋水流问题&#xff1a; 代码详解&#x…

锂电池充放电方式曲线

作为一种“化学能-电能”相互转换的能量装置&#xff0c;锂电池在使用过程中必然会进行充电和放电&#xff0c;合理的充放电方式既能减轻锂电池的损伤程度&#xff0c;又能充分发挥锂电池的性能&#xff0c;具有重要的应用价值。 如《GB/T 31484-2015&#xff1a;电动汽车用动…

非对称齿轮的跨棒距算的对不对

前面有一期咱们聊了非对称齿轮《》&#xff0c;非对称齿轮的齿厚测量一般都为跨棒距。最近研究了下计算方法&#xff0c;对计算结果的正确性做了下验证。 在MATLAB中编制了相关的计算程序&#xff1a; 齿轮的模数4&#xff0c;左侧分度圆压力角25&#xff0c;右侧分度圆压力角…

Sqli-labs第一关到第四关

目录 一&#xff0c;了解PHP源代码 二&#xff0c;破解第一关 2.1在了解完源码之后&#xff0c;我们重点看一下 2.2破解这道题表中有几列 2.3查看表中哪一列有回显 2.4查询库&#xff0c;表&#xff0c;列信息 三&#xff0c;总结 前提&#xff1a; 之所以把1234关…

MySQL基础_1.MySQL概述

文章目录 一、关系型数据库和非关系型数据库1.1 关系型&#xff08;RDBMS&#xff09;1.2 非关系型&#xff08;非RDBMS&#xff09; 二、常用的基础语句2.1 查看表的创建信息2.2 编码问题 一、关系型数据库和非关系型数据库 1.1 关系型&#xff08;RDBMS&#xff09; 是最古…

都上3D数字孪生了,2D的WEB组态和大屏可视化未来的发展在哪里?趋势是基于页面嵌套、蓝图连线等新技术,与功能业务应用融合

首先回顾下组态工具的发展史&#xff1a; 回顾发展史&#xff0c;WEB组态终于可以搭建业务系统了&#xff01;&#xff08;页面嵌套 节点编辑 WEB组态 上位机 大屏可视化 无代码 0代码 iframe nodered 蓝图&#xff09;-CSDN博客文章浏览阅读624次&#xff0c;点赞12次&#x…

ThreeJS:纹理的颜色空间

色彩空间Color Space 在ThreeJS中&#xff0c;纹理的colorSpace属性用于定义文里的颜色空间。 颜色空间是一个用于描述颜色的数学模型&#xff0c;在现实生活中&#xff0c;人眼可以观察到无数种颜色&#xff0c;而颜色空间就是用来描述这些颜色的一个方法&#xff0c;不同的颜…

C语言-自定义类型:结构体,枚举,联合

目录 一、结构体1.1 结构体变量的定义和初始化1.2 结构体内存对齐1.3 修改默认对齐数1.4 结构体传参 二、位段2.1 什么是位段2.2 位段的内存分配2.3 位段的跨平台问题2.4 位段的应用 三、枚举3.1 枚举类型的定义3.2 枚举的优点 四、联合&#xff08;共用体&#xff09;4.1 联合…
最新文章