(三)、基于 LangChain 实现大模型应用程序开发 | 模型链 Chains

😄 为什么我们需要Chains ?

  • 链允许我们将多个组件组合在一起,以创建一个单一的、连贯的应用程序。链(Chains)通常将一个LLM(大语言模型)与提示结合在一起,使用这个构建块,您还可以将一堆这些构建块组合在一起,对您的文本或其他数据进行一系列操作。例如,我们可以创建一个链,该链接受用户输入,使用提示模板对其进行格式化,然后将格式化的响应传递给LLM。我们可以通过将多个链组合在一起,或者通过将链与其他组件组合在一起来构建更复杂的链。
  • 这些链的一部分的强大之处在于你可以一次运行它们在许多输入上。

文章目录

  • 😄 为什么我们需要Chains ?
  • 0、初始化openai环境
  • 1、LLMChain
  • 2、Sequential Chain
    • 2.1、SimpleSequentialChain
    • 2.2、SequentialChain
  • 3、 Router Chain(路由链)
    • 3.1、创建目标链
    • 3.2、创建默认目标链
    • 3.3、创建LLM用于在不同链之间进行路由的模板
    • 3.4、构建路由链
  • Reference

0、初始化openai环境

from langchain.chat_models import ChatOpenAI
import os
import openai
# 运行此API配置,需要将目录中的.env中api_key替换为自己的
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file
openai.api_key = os.environ['OPENAI_API_KEY']

1、LLMChain

  • LLMChain是一个简单但非常强大的链,也是后面我们将要介绍的许多链的基础。
from langchain.chat_models import ChatOpenAI    #导入OpenAI模型
from langchain.prompts import ChatPromptTemplate   #导入聊天提示模板
from langchain.chains import LLMChain    #导入LLM链。# 这里我们将参数temperature设置为0.0,从而减少生成答案的随机性。
# 如果你想要每次得到不一样的有新意的答案,可以尝试调整该参数。
# 以下的对话均无记忆,即每次调用预测不会记得之前的对话。(想要有记忆功能请看下一节的langchain的Memory模块)
llm = ChatOpenAI(temperature=0.0,model_name="gpt-3.5-turbo")
# \在字符串里就是取消换行符的意思
template_string =  """\
对与如下三个反引号括住的评论,我需要提取如下信息。
饮料:这个产品是饮料吗?如果是,返回True,否则返回答False。
产品名:提取出产品的名字,如果没有,返回-1。
价格与价值:提取出关于该产品的价格或价值的所有信息,将他们存入python list中,并返回。
{format_instructions}
```{query}```"""prompt_template = ChatPromptTemplate.from_template(template_string)chain = LLMChain(llm=llm, prompt=prompt_template)query = '这喜茶新出的桑葚葡萄太好喝里吧,而且才19块一杯,太值啦,高性价比!'
format_instructions = """\
将输出组织成带有如下key的json形式:
饮料
产品名
价格与价值"""
res = chain.run({'query':query,'format_instructions': format_instructions})
print(res)
{"饮料": true,"产品名": "桑葚葡萄","价格与价值": ["19块一杯", "高性价比"]
}

2、Sequential Chain

2.1、SimpleSequentialChain

  • 顺序链是按预定义顺序执行其链接的链。具体来说,我们将使用简单顺序链(SimpleSequentialChain),这是顺序链的最简单类型,其中每个步骤都有一个输入/输出,一个步骤的输出是下一个步骤的输入
from langchain.chains import SimpleSequentialChain
first_prompt = ChatPromptTemplate.from_template("描述制造{product}的公司的最佳名称是什么?输出一个即可。"
)
chain_one = LLMChain(llm=llm, prompt=first_prompt)second_prompt = ChatPromptTemplate.from_template("写一个20字的描述对于下面这个\公司:{company_name}"
)
chain_two = LLMChain(llm=llm, prompt=second_prompt)overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],verbose=True)
product = "手机"
overall_simple_chain.run(product)
> Entering new  chain...
Techtronics
Techtronics是一家技术公司,专注于创新和开发高科技产品和解决方案。> Finished chain.'Techtronics是一家技术公司,专注于创新和开发高科技产品和解决方案。'

2.2、SequentialChain

  • 当只有一个输入和一个输出时,简单的顺序链可以顺利完成。但是当有多个输入或多个输出时该如何实现呢?可用顺序链。
from langchain.chains import SequentialChain# 下面实现流程:1->2, 1->3, 2,3->4#子链1
# prompt模板 1: 翻译成英语(把下面的review翻译成英语)
first_prompt = ChatPromptTemplate.from_template("Translate the following review to english:""\n\n{Review}")
# chain 1: 输入:Review 输出: 英文的 Review
chain_one = LLMChain(llm=llm, prompt=first_prompt,output_key="English_Review")#子链2
# prompt模板 2: 用一句话总结下面的 review
second_prompt = ChatPromptTemplate.from_template("Can you summarize the following review in 1 sentence: \n\n{English_Review}")
# chain 2: 输入:英文的Review   输出:总结
chain_two = LLMChain(llm=llm, prompt=second_prompt,output_key="summary")#子链3
# prompt模板 3: 下面review使用的什么语言
third_prompt = ChatPromptTemplate.from_template("What language is the following review:\n\n{Review}")
# chain 3: 输入:Review  输出:语言
chain_three = LLMChain(llm=llm, prompt=third_prompt,output_key="language")#子链4
# prompt模板 4: 使用特定的语言对下面的总结写一个后续回复
# 根据英文总结,翻译成language语言
fourth_prompt = ChatPromptTemplate.from_template("Write a follow up response to the following summary in the specified language:\n\nSummary: {summary}\n\nLanguage: {language}")
# chain 4: 输入: 总结, 语言    输出: 后续回复
chain_four = LLMChain(llm=llm, prompt=fourth_prompt,output_key="followup_message")
overall_chain = SequentialChain(chains=[chain_one, chain_two, chain_three, chain_four],input_variables=["Review"],output_variables=["English_Review", "summary", 'language', "followup_message"],verbose=False)
review = 'Spark是一个快速、通用的大数据处理引擎,可以进行分布式数据处理和分析。与Hadoop的MapReduce相比,Spark具有更高的性能和更丰富的功能。Spark支持多种编程语言(如Scala、Java和Python(pyspark)),并提供了一组丰富的API,包括用于数据处理、机器学习和图计算的库。'
res = overall_chain(review)
type(res), res
(dict,{'Review': 'Spark是一个快速、通用的大数据处理引擎,可以进行分布式数据处理和分析。与Hadoop的MapReduce相比,Spark具有更高的性能和更丰富的功能。Spark支持多种编程语言(如Scala、Java和Python(pyspark)),并提供了一组丰富的API,包括用于数据处理、机器学习和图计算的库。','English_Review': "Spark is a fast and versatile big data processing engine that can perform distributed data processing and analysis. Compared to Hadoop's MapReduce, Spark has higher performance and richer functionality. Spark supports multiple programming languages such as Scala, Java, and Python (pyspark), and provides a rich set of APIs including libraries for data processing, machine learning, and graph computation.",'summary': "The review highlights that Spark is a high-performance and versatile big data processing engine that offers distributed data processing and analysis, surpassing Hadoop's MapReduce in terms of performance and functionality, with support for multiple programming languages and a wide range of APIs for various tasks.",'language': 'The following review is in Chinese.','followup_message': '回复:这篇评论强调了Spark是一个高性能且多功能的大数据处理引擎,提供分布式数据处理和分析,性能和功能方面超过了Hadoop的MapReduce。它支持多种编程语言,并提供各种任务的广泛API。'})

3、 Router Chain(路由链)

到目前为止,我们已经学习了LLM链和顺序链。但是,如果您想做一些更复杂的事情怎么办?

一个相当常见但基本的操作是根据输入将其路由到一条链,具体取决于该输入到底是什么。如果你有多个子链,每个子链都专门用于特定类型的输入,那么可以组成一个路由链,它首先决定将它传递给哪个子链(也输入写prompt模板让llm来选择),然后将它传递给那个链(即传递给对于的链的prompt模板进行预测)。【相当于从输入到输出,要经过两次prompt输入模型拿到输出】

路由器由两个组件组成:

  • 路由器链本身(负责选择要调用的下一个链)
  • destination_chains:路由器链可以路由到的链

个人感觉,就是可以用来根据输入切换不同的设定角色,从而定位到更好的prompt输入给模型预测

举一个具体的例子,让我们看一下我们在不同类型的链之间路由的地方,我们在这里有不同的prompt:

#第一个提示适合回答物理问题
physics_template = """你是一个非常聪明的物理学家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。
问题:{input}"""#第二个提示适合回答数学问题
math_template = """你是一个非常聪明的数学家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。
问题:{input}"""#第三个适合回答历史问题
history_template = """你是一个非常聪明的历史家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。
问题:{input}"""#第四个适合回答计算机问题
computerscience_template = """你是一个非常聪明的计算机学家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。
问题:{input}"""

⭐ 在我们拥有了这些提示模板后,可以为每个模板命名,然后提供描述。例如,第一个物理学的描述适合回答关于物理学的问题,这些信息将传递给路由链,然后由路由链决定何时使用此子链。

prompt_infos = [{"name": "物理","description": "擅长回答物理问题","prompt_template": physics_template},{"name": "数学","description": "擅长回答数学问题","prompt_template": math_template},{"name": "历史","description": "擅长回答历史问题","prompt_template": history_template},{"name": "计算机科学","description": "擅长回答计算机科学问题","prompt_template": computerscience_template}
]

⭐ LLMRouterChain(此链使用 LLM 来确定如何路由事物)
在这里,我们需要一个多提示链。这是一种特定类型的链,用于在多个不同的提示模板之间进行路由。 但是,这只是你可以路由的一种类型。你也可以在任何类型的链之间进行路由。

这里我们要实现的几个类是LLM路由器链。这个类本身使用语言模型来在不同的子链之间进行路由。 这就是上面提供的描述和名称将被使用的地方。

3.1、创建目标链

目标链是由路由链调用的链,每个目标链都是一个语言模型链:

⭐ 将上面定义的4个链用LLMChain构建好,存在destination_chains里:

from langchain.chains.router import MultiPromptChain  #导入多提示链
from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser
from langchain.prompts import PromptTemplatedestination_chains = {}
for p_info in prompt_infos:name = p_info["name"]prompt_template = p_info["prompt_template"]prompt = ChatPromptTemplate.from_template(template=prompt_template)chain = LLMChain(llm=llm, prompt=prompt)destination_chains[name] = chaindestinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)
destination_chains
{'物理': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, tags=None, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='你是一个非常聪明的物理学家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。\n问题:{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None, tiktoken_model_name=None), output_key='text', output_parser=NoOpOutputParser(), return_final_only=True, llm_kwargs={}),'数学': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, tags=None, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='你是一个非常聪明的数学家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。\n问题:{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None, tiktoken_model_name=None), output_key='text', output_parser=NoOpOutputParser(), return_final_only=True, llm_kwargs={}),'历史': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, tags=None, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='你是一个非常聪明的历史家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。\n问题:{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None, tiktoken_model_name=None), output_key='text', output_parser=NoOpOutputParser(), return_final_only=True, llm_kwargs={}),'计算机科学': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, tags=None, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='你是一个非常聪明的计算机学家,你擅长解答物理相关的问题。当你不知道如何解答时你应该承认你不知道。\n问题:{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(cache=None, verbose=False, callbacks=None, callback_manager=None, tags=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key='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', openai_api_base='', openai_organization='', openai_proxy='', request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None, tiktoken_model_name=None), output_key='text', output_parser=NoOpOutputParser(), return_final_only=True, llm_kwargs={})}
destinations, destinations_str
(['物理: 擅长回答物理问题', '数学: 擅长回答数学问题', '历史: 擅长回答历史问题', '计算机科学: 擅长回答计算机科学问题'],'物理: 擅长回答物理问题\n数学: 擅长回答数学问题\n历史: 擅长回答历史问题\n计算机科学: 擅长回答计算机科学问题')

3.2、创建默认目标链

除了目标链之外,我们还需要一个默认目标链。这是一个当路由器无法决定使用哪个子链时调用的链。在上面的示例中,当输入问题与物理、数学、历史或计算机科学无关时,可能会调用它。

default_prompt = ChatPromptTemplate.from_template("{input}")
default_chain = LLMChain(llm=llm, prompt=default_prompt)

3.3、创建LLM用于在不同链之间进行路由的模板

这包括要完成的任务的说明以及输出应该采用的特定格式。

#  以下输出是LLMRouterChain的输出keys是内置的:['destination', 'next_inputs'],所以prompt里定义好它所需的输出MULTI_PROMPT_ROUTER_TEMPLATE = """给定一段原始输入文本,由语言模型来选择对于该段输入\
文本最合适的prompt。我将给定候选prompts和对各prompt适合哪个领域的描述。\
如果您认为修改原始输入最终会导致语言模型得到更好的响应,您也可以修改原始输入。<<格式>>
输出返回如下格式的json对象:
```json
{{{{"destination": string \ name of the prompt to use or "DEFAULT""next_inputs": string \ a potentially modified version of the original input
}}}}
```记住: "destination"一定要是以下候选prompts中的名字之一或者\
如果输入不适合所有候选prompts,destination命名为 “DEFAULT”。
记住: "next_inputs"可以只是原始输入,如果您认为不需要任何修改。<< 候选prompts>>
{destinations}<< 输入 >>
{{input}}<< 输出 (记住包括```json)>>
"""

3.4、构建路由链

首先,我们通过格式化上面定义的目标创建完整的路由器模板。这个模板可以适用许多不同类型的目标。 因此,在这里,您可以添加一个不同的学科,如英语或拉丁语,而不仅仅是物理、数学、历史和计算机科学。

接下来,我们从这个模板创建提示模板

最后,通过传入llm和整个路由提示来创建路由链。需要注意的是这里有路由输出解析,这很重要,因为它将帮助这个链路决定在哪些子链路之间进行路由。

print(destinations_str)
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str
)
router_prompt = PromptTemplate(template=router_template,input_variables=["input"],output_parser=RouterOutputParser(),
)
#  LLMRouterChain的输出keys是内置的:['destination', 'next_inputs'].
router_chain = LLMRouterChain.from_llm(llm, router_prompt)
print(router_chain.output_keys)
物理: 擅长回答物理问题
数学: 擅长回答数学问题
历史: 擅长回答历史问题
计算机科学: 擅长回答计算机科学问题
['destination', 'next_inputs']
router_chain('1+1=?')
{'input': '1+1=?', 'destination': '数学', 'next_inputs': {'input': '1+1=?'}}

最后,将所有内容整合在一起,创建整体链路:

#多提示链
# 设置verbose=True,我们可以看到它被路由到哪条目标prompt链路
chain = MultiPromptChain(router_chain=router_chain,    #路由链路destination_chains=destination_chains,   #目标链路default_chain=default_chain,      #默认链路verbose=True)chain.run("什么是黑体辐射?")
# 物理: {'input': '什么是黑体辐射?'}
# '黑体辐射是指一个理想化的物体,它能够完全吸收所有入射到它上面的辐射能量,并以热辐射的形式重新发射出来。黑体辐射的特点是其辐射能量的分布与温度有关,即黑体辐射谱随着温度的升高而增强,并且在不同波长处的辐射强度也不同。根据普朗克辐射定律和斯蒂芬-玻尔兹曼定律,我们可以描述黑体辐射的性质和行为。'

Reference

  • [1] 吴恩达老师的教程
  • [2] DataWhale组织

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

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

相关文章

永久免费!N个excel表一键合并成一个表(excel表格合并技巧)

您是否还在用手工复制粘贴来将多个EXCEL或表的数据合并到一个表里&#xff1f;那就太麻烦&#xff0c;效率太低了&#xff0c;用金鸣表格文字识别的“表格合并”功能&#xff0c;可免费将N个excel文件或N个excel表一键合并到一个表里面&#xff0c;而且这个功能永久免费&#x…

【C++】特殊类设计 {不能被拷贝的类;只能在堆上创建的类;只能在栈上创建的类;不能被继承的类;单例模式:懒汉模式,饿汉模式}

一、不能被拷贝的类 设计思路&#xff1a; 拷贝只会发生在两个场景中&#xff1a;拷贝构造和赋值重载&#xff0c;因此想要让一个类禁止拷贝&#xff0c;只需让该类不能调用拷贝构造以及赋值重载即可。 C98方案&#xff1a; 将拷贝构造与赋值重载只声明不定义&#xff0c;并…

FDG6306P PowerTrench® MOSFET P沟道 特点及其应用详解

关于PowerTrench MOSFET&#xff1f; 它是一种MOS场效应晶体管&#xff0c;可以提高系统效率和功率密度。该技术采用了屏蔽栅极技术&#xff0c;可以减少开关损耗和导通损耗&#xff0c;从而提高了系统效率。此外&#xff0c;PowerTrench MOSFET还具有低导通电阻和高开关速度的…

三角洲杂志三角洲杂志社三角洲编辑部2023年第19期目录

作家在线 李明聪 把写作当成一种享受 李明聪; 2 头条作品 冬天的童话 王排; 5-7 迎来春色换人间 王排; 8《三角洲》投稿&#xff1a;cnqikantg126.com 小说精选 钢哥 曹茂炯; 9-25 重逢 莫艳阳; 26 散文现场 孩子&#xff0c;你相信光吗&#xff1f; 赵…

前端js语音朗读文本

<!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>语音朗读</title></head><body>&l…

如何满足BMW EDI项目的PKT需求?

近期宝马BMW&#xff08;以下简称BMW&#xff09;在其部分供应商之间试点推进PKT项目&#xff0c;BMW为什么要启动 PKT 计划呢&#xff1f; 业务系统全面升级统一全球所有宝马工厂的流程 宝马内部的物流供货流程 近期BMW PKT需求主要针对其内部物流供货流程展开&#xff1a; …

嵌入式开发--赛普拉斯cypress的铁电存储器FM25CL64B

嵌入式开发–赛普拉斯cypress的铁电存储器FM25CL64B 简介 FM25CL64B是赛普拉斯cypress出品的一款铁电存储器&#xff0c;这种存储器最大的优势是可以像RAM一样随机存储&#xff0c;和按字节写入&#xff0c;也可以像ROM一样掉电仍然可以保存数据&#xff0c;是一种相当优秀的…

Redis 持久化机制

client Redis[内存] --> 内存数据、磁盘数据----> 磁盘&#xff0c;Redis官方提供了两种不同的持久化方案将内存中的数据存储在硬盘中&#xff1a; 快照&#xff08;Snapshot&#xff09; AOF只追加日志文件。 1、快照&#xff08;Snapshot&#xff09; 1、快照的特点…

如何用CHAT解释文章含义?

问CHAT&#xff1a;解释“ 本身乐善好施&#xff0c;令名远近共钦&#xff0c;待等二十左右&#xff0c;定有高亲可攀&#xff1b;而且四德俱备&#xff0c;帮夫之缘亦有。主持家事不紊&#xff0c;上下亦无闲言。但四十交进&#xff0c;家内谨防口舌&#xff0c;须安家堂&…

分布式篇---第一篇

系列文章目录 文章目录 系列文章目录前言一、分布式幂等性如何设计?二、简单一次完整的 HTTP 请求所经历的步骤?三、说说你对分布式事务的了解前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,…

非遗之光:十八数藏柏松数字保护的璀璨之路

随着数字技术的崛起&#xff0c;非物质文化遗产的保护进入了一个新的纪元。在这个时代的先锋中&#xff0c;十八数藏以其对传统工艺的数字保护而独领风骚。这是一条璀璨之路&#xff0c;通过数字技术的应用&#xff0c;为传统工艺注入了新的活力。 十八数藏柏松将数字创新融入传…

软件包管理器yum和git

目录 一、Linux软件包管理器yum 1、Linux下的软件安装方法 2、了解yum 1、实际例子引入 2、yum 3、查找软件包 4、安装软件包 5、卸载软件 二、git 一、Linux软件包管理器yum 1、Linux下的软件安装方法 1、在Linux下安装软件&#xff0c;一个通常的办法是下载到程序的源…

c 一维数组转为二维数组

通过数组指针来转换 用这种方法可以把屏幕mmap 中的数据转为二维的长乘高的数据 #include <stdio.h>int main() {int mm[5] { 0,1,2,3,4 };int (*pm)[3] (int (*)[3])mm; //pm 排 &#xff0c;[3]表示列printf("%d\n", pm[0][2]); // {0,1,2}…

经典百搭女童加绒卫衣,看的见的时尚

经典版型套头卫衣 宽松百搭不挑人穿 单穿内搭都可以 胸口处有精美的小熊印花 面料是复合柔软奥利绒 暖和又不显臃肿哦&#xff01;&#xff01;

Jenkins+Maven+Gitlab+Tomcat 自动化构建打包、部署

JenkinsMavenGitlabTomcat 自动化构建打包、部署 1、环境需求 本帖针对的是Linux环境&#xff0c;Windows或其他系统也可借鉴。具体只讲述Jenkins配置以及整个流程的实现。 1.JDK&#xff08;或JRE&#xff09;及Java环境变量配置&#xff0c;我用的是JDK1.8.0_144&#xff0…

排序算法--快速排序

实现逻辑 ① 从数列中挑出一个元素&#xff0c;称为 “基准”&#xff08;pivot&#xff09;&#xff0c; ② 重新排序数列&#xff0c;所有元素比基准值小的摆放在基准前面&#xff0c;所有元素比基准值大的摆在基准的后面&#xff08;相同的数可以到任一边&#xff09;。在这…

LoRa技术-什么是LoRa

1 概述 LoRa是创建长距离通信连接的物理层无线调制技术&#xff0c;属于CCS&#xff08;线性调制扩频技术&#xff09;的一种&#xff0c;工作频段范围在Sub-1GHz以下。相较于传统的FSK等技术&#xff0c;LoRa在保持低功耗的同时极大地增加了通讯距离&#xff0c;且具备抗干扰…

2023年度openGauss标杆应用实践案例征集

标杆应用实践案例征集 2023 openGauss 数据库作为企业IT系统的核心组成部分&#xff0c;是数字基础设施建设的关键&#xff0c;是实现数据安全稳定的保障。openGauss顺应开源发展趋势&#xff0c;强化核心技术突破&#xff0c;着力打造自主根社区&#xff0c;携手产业伙伴共同…

【开源】基于JAVA的高校实验室管理系统

项目编号&#xff1a; S 015 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S015&#xff0c;文末获取源码。} 项目编号&#xff1a;S015&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实…

这个问题你必须关注!网上申请的流量卡未激活是否可以更换套餐?

资费低&#xff0c;流量多&#xff0c;所以近年来在网上申请流量卡已经成了一种趋势&#xff0c;虽然在网上申请流量卡比较方便&#xff0c;但是很多问题大家都比较迷惑&#xff0c;就比如&#xff0c;下面有私信小编的一个问题。 ​  网友咨询&#xff0c;网上申请的流量卡…