从加载到对话:使用 Llama-cpp-python 本地运行量化 LLM 大模型(GGUF)

(无需显卡)使用 Llama-cpp-python 在本地加载具有 70 亿参数的 LLM 大语言模型,通过这篇文章你将学会用代码创建属于自己的 GPT。
建议阅读完 19a 的「前言」和「模型下载」部分后再进行本文的阅读。

代码文件下载 - Llama-cpp-python

文章目录

  • Llama-cpp-python
    • 环境配置
    • GGUF
      • 安装库
      • 导入库
      • 本地导入模型
      • 自动下载并导入模型
      • 推理测试
      • 卸载到 GPU 加速推理
    • 流式输出
    • 多轮对话
    • 参考链接

Llama-cpp-python

环境配置

为了确保后续的 “offload”(卸载到 GPU)功能正常工作,需要进行一些额外的配置。

首先,找到 CUDA 的安装路径(你需要确保已经安装了 CUDA):

find /usr/local -name "cuda" -exec readlink -f {} \;

参数解释

  • -name "cuda":在 /usr/local 目录下搜索名为 “cuda” 的文件或目录。
  • -exec readlink -f {} \;:对找到的每个文件或目录执行 readlink -f,获取其完整的绝对路径。

假设输出如下:

/usr/local/cuda-12.1
...

复制这个路径,设置 CUDA_HOME 环境变量:

export CUDA_HOME=/usr/local/cuda-12.1

接下来,安装 llama-cpp-python

CMAKE_ARGS="-DGGML_CUDA=on \-DCUDA_PATH=${CUDA_HOME} \-DCUDAToolkit_ROOT=${CUDA_HOME} \-DCUDAToolkit_INCLUDE_DIR=${CUDA_HOME} \-DCUDAToolkit_LIBRARY_DIR=${CUDA_HOME}/lib64 \-DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc" \
FORCE_CMAKE=1 \
pip install --upgrade --force-reinstall llama-cpp-python --no-cache-dir --verbose

[!note]

如果仅在 CPU 上运行,可以直接使用 pip install llama-cpp-python 进行安装。

否则,请确保系统已安装 CUDA,可以通过 nvcc --version 检查。

GGUF

以 bartowski/Mistral-7B-Instruct-v0.3-GGUF 为例进行演示。你将在模型界面查看到以下信息:

image-20241007093704658

可以看到 4-bit 量化有 IQ4_XSQ4_K_SIQ4_NLQ4_K_M 四种,出于性能的考虑,我们将选择 Q4_K_M 进行加载。

文件名量化类型文件大小描述
Mistral-7B-Instruct-v0.3-Q4_K_M.ggufQ4_K_M4.37GB质量较好,权重每位约占 4.83 比特,推荐使用
Mistral-7B-Instruct-v0.3-Q4_K_S.ggufQ4_K_S4.14GB略低于 Q4_K_M 的质量,但节省更多空间,推荐使用
Mistral-7B-Instruct-v0.3-IQ4_NL.ggufIQ4_NL4.13GB质量不错,体积略小于 Q4_K_S,性能相近,推荐使用
Mistral-7B-Instruct-v0.3-IQ4_XS.ggufIQ4_XS3.91GB质量尚可,体积小于 Q4_K_S,性能相近,推荐使用

[!NOTE]

Q:这些量化类型到底是什么?
A:拓展阅读:《d. 如何加载 GGUF 模型(分片/Shared/Split/00001-of-0000…的解决方法)》,其中还会以 Qwen2.5-7B 为例讲述分片模型的加载方式。

安装库

pip install gguf

导入库

from llama_cpp import Llama

下面介绍两种导入模型的方法,实际执行时在本地导入和自动下载中选择一种即可。

本地导入模型

根据模型路径导入模型,注意,文件位于 <model_name> 文件夹下,以当前下载的文件为例:

# 指定本地模型的路径
model_path = "./Mistral-7B-Instruct-v0.3-GGUF/Mistral-7B-Instruct-v0.3-Q4_K_M.gguf"# 加载模型
llm = Llama(model_path=model_path,#n_gpu_layers=-1,  # 取消注释使用 GPU 加速#verbose=False,  # 取消注释禁用详细日志输出
)

自动下载并导入模型

对于 llama-cpp-python,入乡随俗使用 repo_id 变量名,但本质是和之前一致的,filename 可以使用通配符,比如 "*Q4_K_M.gguf"

# 指定仓库的名称和文件名
repo_id = "bartowski/Mistral-7B-Instruct-v0.3-GGUF"
filename = "Mistral-7B-Instruct-v0.3-Q4_K_M.gguf"
#filename = "*Q4_K_M.gguf"  # 使用通配符也是可以的# 下载并加载模型
llm = Llama.from_pretrained(repo_id=repo_id,filename=filename,#n_gpu_layers=-1,  # 取消注释使用 GPU 加速#verbose=False,  # 取消注释禁用详细日志输出
)

[!tip]

二者的函数区别在于 Llama()Llama.from_pretrained()

推理测试

使用以下代码进行简单的推理测试:

# 输入文本
input_text = "Hello, World!"# 生成输出
output = llm(input_text, max_tokens=50)# 打印生成的文本
print(output['choices'][0]['text'])

输出

Llama.generate: 4 prefix-match hit, remaining 1 prompt tokens to eval
llama_perf_context_print:        load time =      28.32 ms
llama_perf_context_print: prompt eval time =       0.00 ms /     1 tokens (    0.00 ms per token,      inf tokens per second)
llama_perf_context_print:        eval time =       0.00 ms /   100 runs   (    0.00 ms per token,      inf tokens per second)
llama_perf_context_print:       total time =    1563.56 ms /   101 tokensWelcome to the latest post on my blog. Today, we will discuss an interesting topic: “How to create a website using JavaScript, HTML, and CSS“. This article is for those who are new to web development or want to learn the basics of creating a website using these technologies. Let’s dive in!# PrerequisitesBefore we start, I would like to mention that I am assuming that you have some basic knowledge of HTML, CSS,

每次生成都会打印一些时间方面的信息,设置 Llama() 的参数 verbose 为 False 可以禁止这个行为。

卸载到 GPU 加速推理

当前的模型默认被部署在 CPU 上,如果你的电脑拥有显卡且大于 5G 显存,那么可以增加 n_gpu_layers 参数将部分计算卸载(offload)到 GPU,以加速推理。修改加载模型的代码如下:

# 本地加载并卸载到 GPU
llm = Llama(model_path=model_path,n_gpu_layers=-1  # 将所有层卸载到 GPUverbose=False,  # 禁用详细日志输出
)# 或者,自动下载并卸载到 GPU
llm = Llama.from_pretrained(repo_id=repo_id,filename=filename,n_gpu_layers=-1  # 将所有层卸载到 GPUverbose=False,  # 禁用详细日志输出
)

如果你的显卡不足 5G,可以设置卸载的具体层数,例如 n_gpu_layers=20,根据你的显存大小调整该参数。

P.S. 不卸载层是允许的,使用 CPU 一样可以进行推理,简单参考下面的表格:

设备tokens/sms/tokens/100 tokens
CPU11.4887.088.71
GPU66.8514.961.50

注:tokens/s 为每秒生成的 Token 数量,ms/token 为生成每个 Token 所需的毫秒数,s/100 tokens 为生成 100 个 Token 所需的秒数。

流式输出

Llama-cpp-python 的流式输出只需要在 create_chat_completion() 中传递参数 stream=True 就可以开启,以本地模型导入为例:

prompt = "人工智能的未来发展方向是什么?"output = llm.create_chat_completion(messages=[{"role": "user","content": prompt}],max_tokens=200,stream=True
)for chunk in output:delta = chunk['choices'][0]['delta']if 'role' in delta:print(delta['role'], end=': ', flush=True)elif 'content' in delta:print(delta['content'], end='', flush=True)

输出

流式输出 llama-cpp-python

代码解释

  • for chunk in output::遍历模型生成的每一个数据块(chunk)。
    • delta = chunk['choices'][0]['delta']

      • 每个chunk包含一个choices列表,这里只取第一个选择(choices[0])。
      • delta包含了当前数据块中的增量信息,可能是角色(role)信息或内容(content)信息。
    • if 'role' in delta:

      • 如果delta中包含'role'键,说明这是角色信息(例如 “assistant”)。
      • print(delta['role'], end=': '):打印角色名,并以冒号和空格结尾,例如“assistant: ”,这是自定义行为,当然也可以 pass 掉。
    • elif 'content' in delta:

      • 如果delta中包含'content'键,说明这是实际的回答内容。
        • print(delta['content'], end=''):打印内容,不换行,以便逐步显示生成的回答,注意,在这里参数 end='' 是正确打印所必须的。

[!note]

查看 output 的构造

from itertools import isliceprompt = "人工智能的未来发展方向是什么?"output = llm.create_chat_completion(messages=[{"role": "user","content": prompt}],max_tokens=200,stream=True
)print(type(output))# 将生成器转换为列表
output_list = list(itertools.islice(output, 3))# 获取前 3 个条目
output_list[:3]

输出(只需要查看其中的 delta):

<class 'generator'>
[{'id': 'chatcmpl-848b2e9b-7d70-4a7b-99aa-74b8206721db',
'model': './Mistral-7B-Instruct-v0.3-GGUF/Mistral-7B-Instruct-v0.3-Q4_K_M.gguf',
'created': 1728562647,
'object': 'chat.completion.chunk',
'choices': [{'index': 0,'delta': {'role': 'assistant'},'logprobs': None,'finish_reason': None}]},
{'id': 'chatcmpl-848b2e9b-7d70-4a7b-99aa-74b8206721db',
'model': './Mistral-7B-Instruct-v0.3-GGUF/Mistral-7B-Instruct-v0.3-Q4_K_M.gguf',
'created': 1728562647,
'object': 'chat.completion.chunk',
'choices': [{'index': 0,'delta': {'content': ' '},'logprobs': None,'finish_reason': None}]},
{'id': 'chatcmpl-848b2e9b-7d70-4a7b-99aa-74b8206721db',
'model': './Mistral-7B-Instruct-v0.3-GGUF/Mistral-7B-Instruct-v0.3-Q4_K_M.gguf',
'created': 1728562647,
'object': 'chat.completion.chunk',
'choices': [{'index': 0,'delta': {'content': '人'},'logprobs': None,'finish_reason': None}]}]

将刚刚对于流式输出的处理抽象为函数便于后续调用:

def handle_stream_output(output):"""处理流式输出,将生成的内容逐步打印出来。参数:output: 生成器对象,来自 create_chat_completion 的流式输出"""for chunk in output:delta = chunk['choices'][0]['delta']if 'role' in delta:print(f"{delta['role']}: ", end='', flush=True)elif 'content' in delta:print(delta['content'], end='', flush=True)# 使用示例
prompt = "人工智能的未来发展方向是什么?"output = llm.create_chat_completion(messages=[{"role": "user","content": prompt}],max_tokens=200,stream=True
)handle_stream_output(output)

函数解释

  • handle_stream_output
    • 接收一个生成器对象 output,遍历每个数据块 chunk
    • 从每个 chunk 中提取 delta 信息。
    • 根据 delta 中的键值,分别处理 rolecontent 信息。
    • 使用 flush=True 确保内容实时打印。

多轮对话

让我们自定义一个交互的对话类(需要注意到 handle_stream_output() 有所修改)。

from llama_cpp import Llamadef handle_stream_output(output):"""处理流式输出,将生成的内容逐步打印出来,并收集完整的回复。参数:output: 生成器对象,来自 create_chat_completion 的流式输出返回:response: 完整的回复文本"""response = ""for chunk in output:delta = chunk['choices'][0]['delta']if 'role' in delta:print(f"{delta['role']}: ", end='', flush=True)elif 'content' in delta:content = delta['content']print(content, end='', flush=True)response += contentreturn responseclass ChatSession:def __init__(self, llm):self.llm = llmself.messages = []def add_message(self, role, content):"""添加一条消息到会话中。参数:role: 消息角色,通常为 'user' 或 'assistant'content: 消息内容"""self.messages.append({"role": role, "content": content})def get_response_stream(self, user_input):"""获取模型对用户输入的响应(流式输出)。参数:user_input: 用户输入的文本返回:response: 完整的回复文本"""self.add_message("user", user_input)try:output = self.llm.create_chat_completion(messages=self.messages,stream=True  # 开启流式输出)response = handle_stream_output(output)  # 同时打印和收集回复self.add_message("assistant", response.strip())return response.strip()except Exception as e:print(f"\n发生错误: {e}")return ""# 初始化模型(假设使用本地路径)
model_path = "./Mistral-7B-Instruct-v0.3-GGUF/Mistral-7B-Instruct-v0.3-Q4_K_M.gguf"
llm = Llama(model_path=model_path,n_gpu_layers=-1,  # 根据需要卸载到 GPUverbose=False,    # 禁用详细日志输出
)# 创建会话实例
chat = ChatSession(llm)# 开始对话
while True:prompt = input("User: ")# 退出对话条件(当然,你也可以直接终止代码块)if prompt.lower() in ["exit", "quit", "bye"]:print("Goodbye!")breakchat.get_response_stream(prompt)print()  # 换行以便下一次输入,这是因为之前的 print 都设置了 end=''

输出

User:  如果你是大模型面试官,你会怎么出面试题
assistant:  以下是一些可能的大模型面试题:1. 解释什么是深度学习和卷积神经网络,以及它们的应用场景。
2. 描述你对数据预处理和特征工程的了解,并提供一个实际使用例子。
3. 如何选择合适的模型、优化器和损失函数,以及如何评估模型性能?
4. 解释你对TensorFlow和PyTorch的了解,并提供一个使用它们的实际例子。
5. 如何处理不平衡数据集,以及你对样本平衡和数据增强方法的了解。
6. 如何使用Transfer Learning来提高模型性能,并提供一个实际例子。
7. 如何使用文本生成模型(如Seq2Seq模型)来进行机器翻译,文本摘要和情感分析?
8. 如何使用对象检测模型(如Faster R-CNN和YOLO)来进行目标检测?
9. 如何使用自编码器来进行数据压缩和特征学习?
10. 如何使用喂给网络(Feeding Networks)和Generative Adversarial Networks(GANs)来生成图像和文本?
11. 如何使用时序数据模型(如ARIMA和LSTM)来进行预测?
12. 如何使用回归树和随机森林来进行预测和分类?
13. 描述你对超参数调优的了解,包括网络架构、学习率和批大小等方面。
14. 如何使用K-means和朴素贝叶斯等聚类和分类方法?
15. 描述你对凸优化和
User:  对于第十个问题能否给我答案发生错误: Requested tokens (530) exceed context window of 512

可以看到报错超过了上下文窗口的长度,让我们增加它:

llm = Llama(model_path=model_path,n_gpu_layers=-1,  # 根据需要卸载到 GPUn_ctx=4096,       # 设置上下文窗口大小verbose=False,    # 禁用详细日志输出
)

此时模型输出正常:

User:  如果你是大模型面试官,你会怎么出面试题
assistant:  以下是一些可能的大模型面试题:1. 解释什么是深度学习和卷积神经网络,以及它们的应用场景。
2. 描述你对数据预处理和特征工程的了解,并提供一个实际使用例子。
3. 如何选择合适的模型、优化器和损失函数,以及如何评估模型性能?
4. 解释你对TensorFlow和PyTorch的了解,并提供一个使用它们的实际例子。
5. 如何处理不平衡数据集,以及你对样本平衡和数据增强方法的了解。
6. 如何使用Transfer Learning来提高模型性能,并提供一个实际例子。
7. 如何使用文本生成模型(如Seq2Seq模型)来进行机器翻译,文本摘要和情感分析?
8. 如何使用对象检测模型(如Faster R-CNN和YOLO)来进行目标检测?
9. 如何使用自编码器来进行数据压缩和特征学习?
10. 如何使用喂给网络(Feeding Networks)和Generative Adversarial Networks(GANs)来生成图像和文本?
11. 如何使用时序数据模型(如ARIMA和LSTM)来进行预测?
12. 如何使用回归树和随机森林来进行预测和分类?
13. 描述你对超参数调优的了解,包括网络架构、学习率和批大小等方面。
14. 如何使用K-means和朴素贝叶斯等聚类和分类方法?
15. 描述你对凸优化和随机 Forests等算法的了解。
User:  对于第十个问题能否给我答案
assistant:  给定一个生成图像和文本的问题,一种方法是使用Generative Adversarial Networks(GANs)。GANs是一种深度学习模型,由两个子网络组成:生成器和判别器。生成器生成一组随机噪声并根据该噪声生成新的数据,而判别器试图区分生成的数据和真实数据。这两个子网络通过最小化一个对抗性损失函数来互相学习。在生成图像方面,常用的GAN模型包括DCGAN(Deep Convolutional GAN)、CGAN(Conditional GAN)和WGAN(Wasserstein GAN)等。DCGAN使用 convolutional neural network 作为生成器,对于生成图像来说,DCGAN可以生成高质量的图像,但是它可能会生成一些不太可靠的图像,因为它是一种无条件生成器。CGAN是DCGAN的一种扩展,它引入了条件信息,允许生成器根据特定条件(如类别标签)生成图像。WGAN是DCGAN的一种改进版本,它使用 Wasserstein 距离来替换了原来的对抗性损失函数,从而使得模型更加稳定。在生成文本方面,常用的GAN模型包括SeqGAN(Sequence Generative Adversarial Nets)和StackGAN(Stack Generative Adversarial Networks)。SeqGAN通过使用RNNs(Recurrent Neural Networks)生成一系列单词来生成文本。StackGAN使用多个堆叠的GAN子网络来生成复杂的文本。总之,GANs是一种强大的生成模型,可以生成高质量的图像和文本,但是它们也有一些问题,例如生成的数据可能存在模式缺陷,并且训练过程可能会收敛很慢。

至此,篇章告一段落 : )。

请注意,这只是一个简短的章节,其中还有许多知识尚未涉及,比如 Transformers 中的 Pipeline,对 Tokenizer 的更深入了解,以及 RAG 的应用等。由于内容过多,文章跳过了一些细节,预计闲暇时增设章节单独进行讲解。

参考链接

  • llama-cpp-python - Docs
  • Example with stream = True? #319

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

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

相关文章

字节跳动青训营开始报名了!

关于青训营&#xff1a; 青训营是字节跳动技术团队发起的技术系列培训 &人才选拔项目;面向高校在校生&#xff0c;旨在培养优秀且具有职业竞争力的开发工程师。 本次技术训练营由掘金联合豆包MarsCode 团队主办课程包含前端、后端和 A 方向&#xff0c;在这个飞速发…

彩族相机内存卡恢复多种攻略:告别数据丢失

在数字时代&#xff0c;相机内存卡作为我们存储珍贵照片和视频的重要媒介&#xff0c;其数据安全性显得尤为重要。然而&#xff0c;意外删除、错误格式化、存储卡损坏等情况时有发生&#xff0c;导致数据丢失&#xff0c;给用户带来不小的困扰。本文将详细介绍彩族相机内存卡数…

服装生产管理的数字化转型:SpringBoot框架

4 系统设计 4.1 系统结构设计 在结构设计过程中&#xff0c;首先对系统进行需求分析&#xff0c;然后进行系统初步设计&#xff0c;将系统功能模块细化&#xff0c;具体分析每一个功能模块具体应该首先哪些功能&#xff0c;最后将各个模块进行整合&#xff0c;实现系统结构的…

R语言的Meta分析【全流程、不确定性分析】方法与Meta机器学习技术应用

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

RelationGraph实现工单进度图——js技能提升

直接上图&#xff1a; 从上图中可以看到整个工单的进度是从【开始】指向【PCB判责】【完善客诉】【PCBA列表】&#xff0c;同时【完善客诉】又可以同时指向【PCB判责】【PCBA列表】&#xff0c;后续各自指向自己的进度。 直接上代码&#xff1a; 1.安装 1.1 Npm 方式 npm …

PostgreSQL学习笔记七:常规SQL操作

PostgreSQL 支持标准的 SQL 语句&#xff0c;同时也扩展了一些特有的功能。以下是一些常规的 SQL 语句示例&#xff0c;这些示例涵盖了数据定义、数据操作和数据查询的基本操作&#xff1a; 数据定义语言 (DDL 创建数据库&#xff1a; CREATE DATABASE mydatabase;创建表&#…

安卓使用.9图实现阴影效果box-shadow: 0 2px 6px 1px rgba(0,0,0,0.08);

1.安卓实现阴影效果有很多种&#xff0c;一般UX设计会给以H5参数box-shadow: 0 2px 6px 1px rgba(0,0,0,0.08);这种方式提供背景阴影效果&#xff0c;这里记录一下实现过程 2.界面xml源码 <?xml version"1.0" encoding"utf-8"?> <layout xmlns…

鸿蒙架构-系统架构师(七十八)

1信息加密是保证系统机密性的常用手段。使用哈希校验是保证数据完整性的常用方法。可用性保证合法用户对资源的正常访问&#xff0c;不会被不正当的拒绝。&#xff08;&#xff09;就是破坏系统的可用性。 A 跨站脚本攻击XSS B 拒绝服务攻击DoS C 跨站请求伪造攻击CSRF D 缓…

MQTT vs HTTP:谁更适合物联网?

前言 随着物联网&#xff08;IoT&#xff09;技术的飞速发展中&#xff0c;其应用规模和使用场景正在持续扩大&#xff0c;但它关键的流程仍然是围绕数据传输来进行的&#xff0c;因此设备通信协议选择至关重要。 作为两种主要的通信协议&#xff0c;MQTT 协议和 HTTP 协议各…

网络资源模板--Android Studio 实现简易计算器App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 实现的简易计算器 二、项目测试环境 三、项目详情 动态绑定按钮&#xff1a; 使用循环遍历 buttons 数组&#xff0c;根据动态生成的按钮 ID (btn_0, …

【环境搭建】MAC M1安装ElasticSearch

STEP1 官网下载ES Download Elasticsearch | Elastic&#xff0c;下载mac m1对应版本的es STEP2 进入bin文件夹&#xff0c;执行./elasticSearch 浏览器输入 127.0.0.1:9200 STEP 3 下载对应Kibana版本&#xff0c;Download Kibana Free | Get Started Now | Elastic 出现报错…

51c自动驾驶~合集3

我自己的原文哦~ https://blog.51cto.com/whaosoft/11506489 #UniAD UniAD是围绕查询设计的&#xff0c;它的感知、预测、规划任务都使用交叉注意力来将前置任务的查询转换为当前任务的查询。每个任务的查询以及这些查询的组合&#xff0c;都用长度为256的向量表征。最初的表…

【Unity】背景图片随着背景里面内容大小而变化

今天制作项目里面的设置界面和暂停界面时&#xff0c;发现两个界面有很多重复部分&#xff0c;所以直接做一个界面就行了&#xff0c;但是两个界面的背景大小会有变化&#xff0c;图片在下面 这个是游戏暂停界面的&#xff0c;设置界面和这个界面有很多重复地方&#xff0c;仅仅…

JavaScript 命令模式实战:打造可撤销的操作命令

一. 前言 在前端开发中&#xff0c;命令模式&#xff08;Command Pattern&#xff09;作为一种行为型设计模式&#xff0c;可以帮助我们将请求封装成一个对象&#xff0c;从而实现调用对象和执行对象之间的解耦&#xff0c;方便扩展和修改。 本文将和大家分享 JavaScript 中的…

知识图谱入门——7:阶段案例:使用 Protégé、Jupyter Notebook 中的 spaCy 和 Neo4j Desktop 搭建知识图谱

在 Windows 环境中结合使用 Protg、Jupyter Notebook 中的 spaCy 和 Neo4j Desktop&#xff0c;可以高效地实现从自然语言处理&#xff08;NLP&#xff09;到知识图谱构建的全过程。本案例将详细论述环境配置、步骤实现以及一些扩展和不足之处。 源文件已上传我的资源区。 文章…

使用 Docker 部署前端项目:Vue 和 React 结合 Nginx 实现静态文件托管

使用 Docker 部署前端项目&#xff1a;Vue 和 React 结合 Nginx 实现静态文件托管 Web 开发中&#xff0c;将前端项目&#xff08;例如 Vue 或 React 应用&#xff09;打包后通过 Docker 容器和 Nginx 部署是非常常见的方式。它不仅简化了部署流程&#xff0c;还能确保在不同环…

4G路由网关R10在智能制造生产线的应用

在当今智能制造的时代&#xff0c;高效稳定的网络连接和数据传输至关重要。4G 路由网关 R10 以其卓越的性能&#xff0c;在智能制造生产线中发挥着重要作用。 4G 路由网关 R10 是一款功能强大的网络设备。它支持多种网络连接方式&#xff0c;包括 4G 网络、有线网络等&#xff…

MySQL连接:内连接

先看我的表结构 dept表 emp表 内连接分为两个连接方式 1.隐式内连接 2.显式内连接 1.隐式内连接 基本语法 select 字段列表 FROM 表1, 表2 WHERE 条件... ;例子&#xff1a;查询每一个员工的姓名&#xff0c;及关联的部门的名称&#xff08;隐式内连接实现&#xff09; …

【C++ STL算法】二分查找 lower_bound、upper_bound、equal_range、binary_search

文章目录 【 1. 首个不小于 lower_bound 】【 2. 首个大于 upper_bound 】【 3. 所有等于 equel_range 】【 4. 二分查找 binary_search 】 当 指定区域内的数据处于有序状态 时&#xff0c;如果想查找某个目标元素&#xff0c;更推荐使用二分查找的方法&#xff08;相比顺序查…

电影选票选座系统|影院购票|电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)

电影院订票选座小程序 目录 基于微信小程序的电影院购票系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户功能实现 2、管理员功能实现 &#xff08;1&#xff09;影院信息管理 &#xff08;2&#xff09;电影信息管理 &#xff08;3&#xff09;已完成…