大模型应用开发框架LangChain

LangChain是什么?

它是针对大语言模型开发的一个开源的抽象框架。下图以github的流行度为例,可以看到langchain在很短的时间流行度达到Pytorch框架的高度,在AI燤火的当下,非常的流行。

上图,可以看到短短不到1年,LangChain的热度就达到Pytorch的高度。

下面这张图,可以理解LangChain作为一个重要开源项目中的地位,它目前是LLM开发的最重要的框架。

为什么需要LangChain?

LangChain 是不是就是 LLM 的 API Warper?这是最容易误解的,当然不是。

统一的大模型标准API的抽象,是它重要的功能,但显然不是全部。

作为框架,它主要还是针对大模型上层应用的开发进行了抽象,并提供了一些标准的功能,提升开发效率。所以,我们关键还是要看看大模型目前到底有哪些应用?

* 大模型的提示词Prompt工程,LangChain提供了相应的TemplateChain。

* 如何提供联网(获取更新的数据),如何使用查数据库等外接工具的通用能力?也就是类似 GPT Plugin 或者 FunctionCall的功能。

* 模型可能是公有云,也可能是本地私有部署的,需要屏蔽掉这种复杂度。

* 应用输出的结果需要再处理,输出要稳定,要合法,要突破token的限制。

类似的问题会很多,你可以理解LangChain会帮助你抽象这些标准的功能,将其变成Chain,而每个Chian中的节点抽象出Runable的接口,使其能方便的执行。

LangChain的典型应用场景

从目前最流行的RAG应用为例 ,可以看到langChain在一个知识库检索型项目中起到的作用,实际上它就是将各种技术通过链条的方式串到了一起。

简单理解就是:

第一步:embeding模型 完成输入问题的编码。

第二步:在向量库中进行检索,获取相关知识。

第三步:LLM模型,对答案进行组织,返回。

可以进一步看一下它的最重要的功能模块:

这些模块也基本函概了目前最重要的大模型的应用。

LangChain 核心模块

Model I/O

大模型的输入就是 Prompt :被封装成了Template(提供变量),模块化,动态选择和管理模型的输入。

大模型的执行部分就是 Model,针对各种各样的大模型,以通用接口调用各种语言模型(不清楚有什么组织在统一接口,可能目前主要以OpenAI的GPT为标准模型)。

大模型的输出结果,可以通过一个Parser来保证输出更稳定(输出的解板器,将输出规范化),从模型输出中提出信息,并规范化内容。这个很重要,因为作为Chain框架,最重要的就是每一个处理都可以作为下一个处理的输入,那这就要求输出必须可以进行相应的定制。

给合联网查询的实例

对于一个扩展的问答,可以追加联网搜索,本地组存(向量化 RAG)来实现,如下图所示。这就是一个比较典型的大模型应用。给合了联网功能,RAG功能。

支持的大模型

LLMs | 🦜️🔗 LangChainFeatures (natively supported)icon-default.png?t=N7T8https://python.langchain.com/v0.2/docs/integrations/llms/        从上面的清单可以看出,流行的大模型它基本都支持。

大语言模型(LLMs)

BaseLanguageModel --> BaseLLM --> LLM --> <name>  # Examples: AI21, HuggingFaceHub, OpenAI

from langchain_openai import OpenAIllm = OpenAI(model_name="gpt-3.5-turbo-instruct")print(llm("Tell me a Joke"))#输出
Why did the tomato turn red? Because it saw the salad dressing!

聊天模型(Chat Models)

BaseLanguageModel --> BaseChatModel --> <name>  

# Examples: ChatOpenAI, ChatGooglePalm

from langchain_openai import ChatOpenAIchat_model = ChatOpenAI(model_name="gpt-3.5-turbo")from langchain.schema import (AIMessage,HumanMessage,SystemMessage
)messages = [SystemMessage(content="You are a helpful assistant."),HumanMessage(content="Who won the world series in 2020?"),AIMessage(content="The Los Angeles Dodgers won the World Series in 2020."), HumanMessage(content="Where was it played?")]chat_model(messages)# 以下非代码
# 运行的输出
AIMessage(
content='The 2020 World Series was played at Globe Life Field in Arlington, Texas.', 
response_metadata=
{'token_usage': {'completion_tokens': 17, 'prompt_tokens': 53, 'total_tokens': 70}, 
'model_name': 'gpt-3.5-turbo', 
'system_fingerprint': 'fp_3bc1b5746c', 
'finish_reason': 'stop', 
'logprobs': None}
)

提示词模板(PromptTemplate)

普通提示词模板的使用非常简单,如下:

from langchain import PromptTemplateprompt_template = PromptTemplate.from_template("讲{num}个给程序员听得笑话"
)from langchain_openai import OpenAIllm = OpenAI(model_name="gpt-3.5-turbo-instruct", max_tokens=1000)prompt = prompt_template.format(num=2)
print(f"prompt: {prompt}")result = llm(prompt)
print(f"result: {result}")#输出如下
prompt: 讲2个给程序员听得笑话
result: 1. 为什么程序员总是喜欢用黑色的键盘?
因为黑色的键盘会让程序员的代码看起来更酷。2. 为什么程序员总是喜欢坐在屏幕前工作?
因为他们知道,屏幕前的世界才是真正的世界,而现实世界只是一个bug。

如果是聊天类的提示词,可以见如下示例 :

from langchain.prompts import ChatPromptTemplatetemplate = ChatPromptTemplate.from_messages([("system", "You are a helpful AI bot. Your name is {name}."),("human", "Hello, how are you doing?"),("ai", "I'm doing well, thanks!"),("human", "{user_input}"),
])# 生成提示
messages = template.format_messages(name="Bob",user_input="What is your name?"
)from langchain.chat_models import ChatOpenAI
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", max_tokens=1000)chat_model(messages)#输出
AIMessage(
content='My name is Bob. How can I help you today?', 
response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 50, 'total_tokens': 62}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, 
id='run-09e40efb-8c7e-4c1c-be27-591232de9a47-0')

对于相关的任务,除了对话,还可以做摘要,翻译等任务。

另外,还可以使用 FewShotPromtTemplate 来完成FewShot的提示方式。

 规范化输出(output parser)

下面的例子,是针对List格式的输出:

from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_openai import OpenAI# 创建一个输出解析器,用于处理带逗号分隔的列表输出
output_parser = CommaSeparatedListOutputParser()# 获取格式化指令,该指令告诉模型如何格式化其输出
format_instructions = output_parser.get_format_instructions()# 创建一个提示模板,它会基于给定的模板和变量来生成提示
prompt = PromptTemplate(template="List five {subject}.\n{format_instructions}",  # 模板内容input_variables=["subject"],  # 输入变量partial_variables={"format_instructions": format_instructions}  # 预定义的变量,这里我们传入格式化指令
)# 使用提示模板和给定的主题来格式化输入
_input = prompt.format(subject="ice cream flavors")output = llm(_input)print(output)# 使用之前创建的输出解析器来解析模型的输出
output_parser.parse(output)#输出1 print(output)1. Chocolate
2. Vanilla
3. Strawberry
4. Mint chocolate chip
5. Cookies and cream#输出2 output_parser
['1. Chocolate\n2. Vanilla\n3. Strawberry\n4. Mint chocolate chip\n5. Cookies and cream']

上面例子的关键是:CommaSeparatedListOutputParser 

用法是:使用格式化模板的提示词(追加)

output_parser = CommaSeparatedListOutputParser()
format_instructions = output_parser.get_format_instructions()
template="List five {subject}.\n{format_instructions}",  # 模板内容

将输出进行 Parse:

output_parser.parse(output)

同理,如果要进行日期格式化,可以使用DatetimeOutputParser。LangChain框架还提供了一些其它模板。但是注意:因为是提示词,所以,它并不确保一定执行有效。

Chain的用法

LLMChain (大模型基础链)

最基础,最简单的就是LLMChain,也是使用LLM来进行问答。它会作为其它复杂Chain的基础,以及Agent的基础单元。

SequentialChain: 串联式调用语言模型链

串联式的链分为2种,一种是 SimpleSequentialChain,只接受单输入/单输出。

还有一种是更通用的 SequentialChain,它接受多输入,多输出。

TransformerChian:处理文本的转换链(包装链)

        其实,这就是对Python转换的一种封装,将Python的处理工具和步骤封装进去。

RouterChian:实现条件判断

Memory 的用法

Memory主要还是为了解决对话的上下文的记忆问题。

一次对话后,是否将对话回写到内存。下次对话前,是否需要复用内存中的内容。

·························

对于Memory的实现,需要继承自 BaseMemory

BaseMemory --> BaseChatMemory --> <name>Memory  # Examples: ZepMemory, MotorheadMemory

BaseChatMessageHistory --> <name>ChatMessageHistory  # Example: ZepChatMessageHistory

今天重点只看ChatMemory,官方提供了三种实现:

ConversationBufferMemory :记录所有会话上下文

from langchain_openai import OpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemoryllm = OpenAI(temperature=0)
conversation = ConversationChain(llm=llm, verbose=True, memory=ConversationBufferMemory()
)conversation.predict(input="你好呀!")conversation.predict(input="你为什么叫小米?跟雷军有关系吗?")#输出> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.Current conversation:
Human: 你好呀!
AI:  你好!我是一個人工智能助手。我可以回答你的問題,或者和你聊天。你有什麼需要幫助的嗎?Human: 我想知道你是如何工作的。
AI: 我是通過學習和訓練來工作的。我的開發者們為我提供了大量的數據和算法,讓我能夠理解和處理人類的語言和指令。我也會不斷地學習和改進自己的能力,以更好地為人類服務。Human: 那你是如何學習的呢?
AI: 我的學習過程主要是通過機器學習和深度學習來實現的。這些技術讓我能
Human: 你为什么叫小米?跟雷军有关系吗?
AI:> Finished chain.

ConversationBufferWindowMemory:记录指定次数的上下文

如题,可以带一个参数N,保存N次上下文。

ConversationSummaryBufferMemory:摘要记录上下文

如题,会将上下文进行压缩/摘要,记录重要信息

数据流处理

对于数据的处理,有5大功能——装载文档,转换,转向量,存入向量数据库,检索。

文档装载(Document Load)

支持一些典型的文件格式:CSV,HTML,JSON,Markdown,PDF,FileDirectory……

from langchain.document_loaders import TextLoaderdocs = TextLoader('../tests/state_of_the_union.txt','utf-8').load()docs#输出
[Document(page_content='文档内容(略).', 
metadata={'source': '../tests/state_of_the_union.txt'})]

支持一些标准的数据源:ArXiv,Discord,GitHub,Reddit,TensorFlow DataSet……

ArXiv是一个论文平台,比如,GPT 论文的链接:

https://arxiv.org/abs/2005.14165

from langchain.document_loaders import ArxivLoader#GPT3的论文地址
query = "2005.14165"docs = ArxivLoader(query=query, load_max_docs=5).load()docs[0].metadata  # meta-information of the Document#输出
{'Published': '2020-07-22','Title': 'Language Models are Few-Shot Learners','Authors': 'Tom B. Brown, Benjamin Mann, Nick Ryder, Melanie Subbiah, Jared Kaplan, Prafulla Dhariwal, Arvind Neelakantan, Pranav Shyam, Girish Sastry, Amanda Askell, Sandhini Agarwal, Ariel Herbert-Voss, Gretchen Krueger, Tom Henighan, Rewon Child, Aditya Ramesh, Daniel M. Ziegler, Jeffrey Wu, Clemens Winter, Christopher Hesse, Mark Chen, Eric Sigler, Mateusz Litwin, Scott Gray, Benjamin Chess, Jack Clark, Christopher Berner, Sam McCandlish, Alec Radford, Ilya Sutskever, Dario Amodei','Summary': "主要的内容,此处略."}

文档转换(Docment Transformer)

加载好文档后,肯定是进行转换。

比如:RecursiveCharacterTextSplitter

这里就不举例了,和普通的转换是一样的。

文本嵌入/编码/向量化(Embed)

这是一个非常重要的环节,实际上在没有大模型之前,文本也有一些方法来检索,比如:ES,Solor之类的全文本索引的方式。但现在流行的当然是Embed模型,所有支持的方法有如下:

相关代码我就不贴,我之前专门一篇博客讲这个的,有兴趣可以去看看。

Embedding技术学习-CSDN博客

向量数据库(Vector DB)写入

接下来就是向量数据库了,这个应该是有不少标准的实现的,也有一些云服务。

以最简单的Chroma为例(实际上还有内存方式的向量库)

from langchain.document_loaders import TextLoader
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma# 加载长文本
raw_documents = TextLoader('../tests/state_of_the_union.txt',encoding='utf-8').load()# 实例化文本分割器
text_splitter = CharacterTextSplitter(chunk_size=200, chunk_overlap=0)# 分割文本
documents = text_splitter.split_documents(raw_documents)embeddings_model = OpenAIEmbeddings()# 将分割后的文本,使用 OpenAI 嵌入模型获取嵌入向量,并存储在 Chroma 中
db = Chroma.from_documents(documents, embeddings_model)query = "What did the president say about Ketanji Brown Jackson"
docs = db.similarity_search(query)
print(docs[0].page_content)#输出
And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji 
Brown Jackson. One of our nation’s top legal minds, who will continue Justice 
Breyer’s legacy of excellence.


数据检索器 Retrieves:

最后就是从向量数据库中查找内容了,上面已有示例。

如何构建Agent

将推理和行动结合起来,ReAct是重要的方式之一。

如何实现ReAct,看下面的示例 :

其中的核心就是分步骤,提供外部工具箱,设定终止条件。

有如下tools:

当然,ReAct只是构建Agent 的方式之一,其实还有一些其它方式。

自定义Agent

第一种方式,就是自已定义一个tools,生成Agent,完成任务。

from langchain_openai import ChatOpenAI# 使用 GPT-3.5-turbo
llm = ChatOpenAI(temperature=0)from langchain.agents import tool@tool
def get_word_length(word: str) -> int:"""Returns the length of a word."""return len(word)tools = [get_word_length]from langchain.schema import SystemMessage
from langchain.agents import OpenAIFunctionsAgentsystem_message = SystemMessage(content="你是非常强大的AI助手,但在计算单词长度方面不擅长。")
prompt = OpenAIFunctionsAgent.create_prompt(system_message=system_message)agent = OpenAIFunctionsAgent(llm=llm, tools=tools, prompt=prompt)from langchain.agents import AgentExecutor# 实例化 OpenAIFunctionsAgent
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)agent_executor.run("单词“educa”中有多少个字母?")#输出
> Entering new AgentExecutor chain...Invoking: `get_word_length` with `{'word': 'educa'}`5单词“educa”中有5个字母。> Finished chain.

注意,如果我们想在上面的agent添加Memory,非常简单(成功的记忆了上次对话的内容)

from langchain.prompts import MessagesPlaceholderMEMORY_KEY = "chat_history"
prompt = OpenAIFunctionsAgent.create_prompt(system_message=system_message,extra_prompt_messages=[MessagesPlaceholder(variable_name=MEMORY_KEY)]
)from langchain.memory import ConversationBufferMemorymemory = ConversationBufferMemory(memory_key=MEMORY_KEY, return_messages=True)agent = OpenAIFunctionsAgent(llm=llm, tools=tools, prompt=prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, memory=memory, verbose=True)agent_executor.run("单词“educa”中有多少个字母?")agent_executor.run("那是一个真实的单词吗?")#输出
> Entering new AgentExecutor chain...
抱歉,我无法确定“educa”是否是一个真实的单词。您可以查阅字典或在线搜索以确认该单词的存在。> Finished chain.

Self_Ask_with_search

这是一种常用的Agent,自问自答,非常的常用。

self_ask_with_search = initialize_agent(

    tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True

)

import os# 更换为自己的 Serp API KEY
os.environ["SERPAPI_API_KEY"] = "这需要自行去注册"  #注册网站:https://serpapi.comfrom langchain_openai import OpenAI
from langchain.utilities import SerpAPIWrapper
from langchain.agents import initialize_agent, AgentType, Toolllm = OpenAI(temperature=0)# 实例化查询工具
search = SerpAPIWrapper()
tools = [Tool(name="Intermediate Answer",func=search.run,description="useful for when you need to ask with search",)
]# 实例化 SELF_ASK_WITH_SEARCH Agent
self_ask_with_search = initialize_agent(tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True
)# 实际运行 Agent,查询问题
self_ask_with_search.run("成都举办的大运会是第几届大运会?"
)

React Agent 

import os# 更换为自己的 Serp API KEY
os.environ["SERPAPI_API_KEY"] = "自己注册APIKey"from langchain_openai import OpenAIllm = OpenAI(temperature=0)from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType#加载 LangChain 内置的 Tools
tools = load_tools(["serpapi", "llm-math"], llm=llm)# 实例化 ZERO_SHOT_REACT Agent
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)agent.run("谁是莱昂纳多·迪卡普里奥的女朋友?她现在年龄的0.43次方是多少?")#输出
> Entering new AgentExecutor chain...I should use the search engine to find information about Leonardo DiCaprio's girlfriend.
Action: Search
Action Input: "Leonardo DiCaprio girlfriend"
Observation: Vittoria Ceretti
Thought: Now I need to use the calculator to calculate 0.43 times the age of Vittoria Ceretti.
Action: Calculator
Action Input: 0.43 * 23
Observation: Answer: 9.89
Thought: I now know the final answer.
Final Answer: 9.89> Finished chain.

如果换成GPT-4,效果会好很多。

from langchain_openai import ChatOpenAIchat_model = ChatOpenAI(model="gpt-4-1106-preview", temperature=0)
agent = initialize_agent(tools, chat_model, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run("谁是莱昂纳多·迪卡普里奥的女朋友?她现在年龄的0.43次方是多少?")#输出
> Entering new AgentExecutor chain...
Question: 谁是莱昂纳多·迪卡普里奥的女朋友?
Thought: To find out who Leonardo DiCaprio's current girlfriend is, I will use the search tool.
Action:
```json
{"action": "Search","action_input": "Leonardo DiCaprio current girlfriend 2023"
}
```Observation: Vittoria Ceretti (2023 - present) Leonardo DiCaprio and Vittoria Ceretti's relationship first started making headlines in August 2023. The pair were first spotted together in Ibiza, Spain. In a video obtained by Page Six, the pair could be seen dancing with each another at a nightclub, Hï Ibiza.
Thought:Thought: Now that I know Leonardo DiCaprio's current girlfriend is Vittoria Ceretti, I need to find out her age to calculate the 0.43 power of her age.Action:
```json
{"action": "Search","action_input": "Vittoria Ceretti age"
}```...Final Answer: The 0.43 power of Vittoria Ceretti's age, who is 26 years old, is approximately 4.06.> Finished chain.

对于Agent,我的理解是,它能完成ChatGPT这种纯会话应用无法完成的一些其它功能,当然,它需要编程,需要将输入,转换,大语言模型能力,输出,串联起来,完成更复杂的功能。

当然,要更进一步,就是AutoGPT的方式了,这个在后面再进行学习和理解。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AMD在行动:揭示应用程序跟踪和性能分析的力量

AMD in Action: Unveiling the Power of Application Tracing and Profiling — ROCm Blogs 导言 Rocprof是一款强大的工具&#xff0c;设计用于分析和优化基于AMD ROCm平台上运行的HIP程序的性能&#xff0c;帮助开发者找出并解决性能瓶颈。Rocprof提供了多种性能数据&#x…

每日一题——Python实现PAT乙级1099 性感素数(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 专业点评 时间复杂度分析 空间复杂度分析 综合点评 我要更强 优化点 …

人事信息管理系统(Java+MySQL)

一、项目背景 在现代企业中&#xff0c;管理大量员工的工作信息、薪资、请假、离职等事务是一项非常繁琐和复杂的任务。传统的手工管理方式不仅效率低下&#xff0c;而且容易出错。为了提高人事管理的效率&#xff0c;减少人工操作带来的错误&#xff0c;企业迫切需要一个高效…

【JAVASE】详讲java案例(中)

这篇接着讲用java语言写程序&#xff0c;本篇文章要讲三道题&#xff1a; &#xff08;1&#xff09;数字加密 &#xff08;2&#xff09;数组拷贝 &#xff08;3&#xff09;打印乘法表 一&#xff1a;数字加密 需求&#xff1a;某系统的数字密码是一个四位数&#xff0c…

【Leetcode】881. 救生艇

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 点击打开题目链接&#x1f517; 给定数组 p e o p l e people people 。 p e o p l e [ i ] people[i] people[i]表示第 i i i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重…

【李宏毅-生成式 AI】Spring 2024, HW5:LLM Fine-tuning 实验记录

文章目录 1. Task Overview2. Overall Workflow3. Dataset 介绍4. 代码介绍4.1 环境介绍4.2 下载 dataset4.3 下载并加载模型4.2 Notebook 代码1&#xff09;import 部分2&#xff09;固定 seed3&#xff09;加载 LLM4&#xff09;加载 tokenizer5&#xff09;设置解码参数6&am…

tcp协议的延迟应答(介绍+原则),拥塞控制(拥塞窗口,网络出现拥塞时,滑动窗口的大小如何确定,慢启动,阈值)

目录 延迟应答 引入 介绍 原则 拥塞控制 引入 网络出现拥塞 引入 介绍 介绍 拥塞窗口 介绍 决定滑动窗口的大小 慢启动 介绍 为什么要有慢启动 阈值 算法 总结 延迟应答 引入 发送方一次发送更多的数据,发送效率就越高 因为要写入网卡硬件的io速度很慢,尽量…

conda 创建环境失败

conda create -n pylableimg python3.10在conda &#xff08;base&#xff09;环境下&#xff0c;创建新的环境&#xff0c;失败。 报错&#xff1a; LookupError: didn’t find info-scipy-1.11.3-py310h309d312_0 component in C:\Users\Jane.conda\pkgs\scipy-1.11.3-py310h…

英伟达:史上最牛一笔天使投资

200万美元的天使投资&#xff0c;让刚成立就面临倒闭风险的英伟达由危转安&#xff0c;并由此缔造了一个2.8万亿美元的市值神话。 这是全球风投史上浓墨重彩的一笔。 前不久&#xff0c;黄仁勋在母校斯坦福大学的演讲中&#xff0c;提到了人生中的第一笔融资——1993年&#x…

刷代码随想录有感(98):动态规划——爬楼梯

题干&#xff1a; 代码&#xff1a; class Solution { public:int climbStairs(int n) {if(n 1)return 1;if(n 2)return 2;vector<int>dp(n 1);dp[0] 0;dp[1] 1;dp[2] 2;for(int i 3; i < n; i){dp[i] dp[i - 1] dp[i - 2];}return dp[n];} }; 其实就是斐波…

liquibase做数据库版本管理

通过这个配置就会自动启动liquibase 比对 https://www.cnblogs.com/ludangxin/p/16676701.html https://zhuyizhuo.github.io/2020/07/04/spring-boot/spring-boot-liquibase-database-version-control/

上市公司短视主义数据集(2001-2022年)

数据简介&#xff1a;上市公司短视主义是指公司管理层过于关注短期业绩和股价表现&#xff0c;而忽视公司的长期发展和战略规划。这种短视行为可能会导致公司投资决策的失误&#xff0c;影响公司的长期竞争力。 在上市公司年度报告年度中&#xff0c;通过已有的反映管理者“短…

Excel 将同一分类下的值依次填进分类格右边的格中

表格的第2列是分类&#xff0c;第3列是明细&#xff1a; ABC1S.noAccountProduct21AAAQatAAG32BAAQbIAAW43BAAQkJAAW54CAAQaAAP65DAAQaAAX76DAAQbAAX87DAAQcAAX 需要将同一分类下的值依次填入分类格右边的格中&#xff1a; ABCD1S.noAccountProduct21AAAQatAAG32BAAQbIAAWkJ…

快速安装Windows和Ubuntu双系统

一、参考资料 用UltraISO制作Ubuntu16.04 U盘启动盘 DiskPart Command-Line Options 二、相关介绍 1. MBR和GPT分区模式 MBR分区模式 MBR最大仅支持2TB磁盘&#xff0c;超过2TB不可识别。 MBR&#xff08;Master Boot Record&#xff09;&#xff0c;即硬盘的主引导记录分…

【激光雷达】

激光雷达 机械式360扫描雷达半固态激光雷达二维扫描一维扫描 固态激光雷达OPA固态激光雷达&#xff08; 光学相控阵技术&#xff09; FMCW 激光雷达 激光雷达技术在近几年可以说是蓬勃发展&#xff0c;新能源汽车的大量使用&#xff0c;给雷达技术的发展提供了肥沃的土壤&#…

嵌入式作业6

1、利用SysTick定时器编写倒计时程序&#xff0c;如初始设置为2分30秒&#xff0c;每秒在屏幕上输出一次时间&#xff0c;倒计时为0后&#xff0c;红灯亮&#xff0c;停止屏幕输出&#xff0c;并关闭SysTick定时器的中断。 2、利用RTC显示日期&#xff08;年月日、时分秒&…

【C++类和对象中篇】(构造函数和析构函数)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f369;1.默认成员函数的概念&#xff1a; &#x1f369;2.构造函数&#xff1a; 2.1特性&…

从零开始理解AdaBoost算法:设计思路与算法流程(二)【权值更新与加权表决、数学公式】

设计思路 AdaBoost算法属于Boosting算法家族中的一种&#xff0c;其基本思路是将多个弱分类器组合成一个强分类器。 “强分类器”是指一个分类准确率较高的模型“弱分类器”则是指分类准确率略高于随机猜测的简单模型。 AdaBoost的核心思想是通过 加权 的方式逐步提高分类器…

黑马es学习

es 0. 基础概念0.1 倒排索引0.2 文档、索引0.3 与mysql对比 1 基本操作1.1 mapping 索引库操作1.2 单个文档CRUD 3. DSL查询3.1 查询所有3.2 全文检索3.3 精确查询3.4 复合查询-相关性得分3.5 分页3.6 高亮3.7 总结 2. RestClientmysql与es数据同步es集群去重 黑马视频 官方使…

Docker:利用Docker搭建一个nginx服务

文章目录 搭建一个nginx服务认识nginx服务Web服务器反向代理服务器高性能特点 安装nginx启动nginx停止nginx查找nginx镜像拉取nginx镜像&#xff0c;启动nginx站点其他方式拉取nginx镜像信息通过 DIGEST 拉取镜像 搭建一个nginx服务 首先先认识一下nginx服务&#xff1a; NGI…