Qwen2.5-7B-Instruct vLLM 部署调用

Qwen2.5-7B-Instruct vLLM 部署调用

vLLM 简介

vLLM 框架是一个高效的大语言模型推理和部署服务系统,具备以下特性:

  • 高效的内存管理:通过 PagedAttention 算法,vLLM 实现了对 KV 缓存的高效管理,减少了内存浪费,优化了模型的运行效率。
  • 高吞吐量vLLM 支持异步处理和连续批处理请求,显著提高了模型推理的吞吐量,加速了文本生成和处理速度。
  • 易用性vLLMHuggingFace 模型无缝集成,支持多种流行的大型语言模型,简化了模型部署和推理的过程。兼容 OpenAIAPI 服务器。
  • 分布式推理:框架支持在多 GPU 环境中进行分布式推理,通过模型并行策略和高效的数据通信,提升了处理大型模型的能力。
  • 开源共享vLLM 由于其开源的属性,拥有活跃的社区支持,这也便于开发者贡献和改进,共同推动技术发展。

环境准备

本文基础环境如下:

----------------
ubuntu 22.04
python 3.12
cuda 12.1
pytorch 2.4.0
----------------

本文默认学习者已配置好以上 Pytorch (cuda) 环境,如未配置请先自行安装。

首先 pip 换源加速下载并安装依赖包

python -m pip install --upgrade pip
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepip install modelscope==1.20.0
pip install transformers==4.46.2
pip install torch==2.4.0 torchvision==0.19.0 torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cu121
pip install vllm==0.6.3.post1
pip install accelerate==0.26.0

考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Qwen2.5的环境镜像,点击下方链接并直接创建Autodl示例即可。
https://www.codewithgpu.com/i/datawhalechina/self-llm/qwen2.5-coder

模型下载

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

在新建 model_download.py 文件并在其中输入以下内容,粘贴代码后记得保存文件,如下图所示。并运行 python model_download.py 执行下载,模型大小为 16 GB,下载模型大概需要 12 分钟。

from modelscope import snapshot_downloadsnapshot_download('Qwen/Qwen2.5-Coder-7B-Instruct', local_dir='/root/autodl-tmp/Qwen2.5-Coder-7B-Instruct')

注意:记得修改 local_dir 为你的模型下载路径哦~
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码准备

Python脚本

/root/autodl-tmp 路径下新建 vllm_model.py 文件并在其中输入以下内容,粘贴代码后请及时保存文件。下面的代码有很详细的注释,如有不理解的地方,欢迎大家提 issue

首先从 vLLM 库中导入 LLMSamplingParams 类。LLM 类是使用 vLLM 引擎运行离线推理的主要类。SamplingParams 类指定采样过程的参数,用于控制和调整生成文本的随机性和多样性。

vLLM 提供了非常方便的封装,我们直接传入模型名称或模型路径即可,不必手动初始化模型和分词器。

我们可以通过这个代码示例熟悉下 vLLM 引擎的使用方式。被注释的部分内容可以丰富模型的能力,但不是必要的,大家可以按需选择,自己多多动手尝试 ~

# vllm_model.py
from vllm import LLM, SamplingParams
from transformers import AutoTokenizer
import os
import jsondef prepare_model(model_path,  max_tokens=512, temperature=0.8, top_p=0.95, max_model_len=2048):# 初始化 vLLM 推理引擎llm = LLM(model=model_path, tokenizer=model_path, max_model_len=max_model_len,trust_remote_code=True)return llmdef get_completion(prompts, llm, max_tokens=512, temperature=0.8, top_p=0.95, max_model_len=2048):stop_token_ids = [151329, 151336, 151338]# 创建采样参数。temperature 控制生成文本的多样性,top_p 控制核心采样的概率sampling_params = SamplingParams(temperature=temperature, top_p=top_p, max_tokens=max_tokens, stop_token_ids=stop_token_ids)# 初始化 vLLM 推理引擎outputs = llm.generate(prompts, sampling_params)return outputs# 初始化 vLLM 推理引擎
model_path = './Qwen2.5-Coder-7B-Instruct'
tokenizer = AutoTokenizer.from_pretrained(model_path)
llm = prepare_model(model_path)prompt = "帮我使用torch写一个用于手写数字识别的模型"
messages = [{"role": "system", "content": "你是一个有用的助手。"},{"role": "user", "content": prompt}
]# 应用template中的chat模板
text = tokenizer.apply_chat_template(messages,tokenize=False,add_generation_prompt=True
)outputs = get_completion(text, llm, max_tokens=1024, temperature=1, top_p=1, max_model_len=2048)
print(outputs[0].outputs[0].text)

运行代码

cd /root/autodl-tmp && python vllm_model.py

结果如下:

Prompt: '帮我使用torch写一个用于手写数字识别的模型', Generated text: ' 当然可以!下面是一个使用PyTorch编写的简单卷积神经网络(CNN),用于手写数字识别。这个模型使用的是MNIST数据集。\n\n首先,确保你已经安装了PyTorch。如果没有安装,可以使用以下命令进行安装:\n\n```bash\npip install torch torchvision\n```\n\n接下来是代码:\n\n```python\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nimport torchvision.transforms as transforms\n\n# 定义超参数\nbatch_size = 64\nlearning_rate = 0.001\nnum_epochs = 10\n\n# 转换数据\ntransform = transforms.Compose([\n    transforms.ToTensor(),\n])\n\n# 加载MNIST数据集\ntrain_dataset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)\ntest_dataset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)\n\n# 创建数据加载器\ntrain_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)\ntest_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)\n\n# 定义卷积神经网络模型\nclass CNN(nn.Module):\n    def __init__(self):\n        super(CNN, self).__init__()\n        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1)\n        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1)\n        self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)\n        self.fc1 = nn.Linear(in_features=64 * 7 * 7, out_features=128)\n        self.fc2 = nn.Linear(in_features=128, out_features=10)\n\n    def forward(self, x):\n        x = self.pool(nn.functional.relu(self.conv1(x)))\n        x = self.pool(nn.functional.relu(self.conv2(x)))\n        x = x.view(-1, 64 * 7 * 7)\n        x = nn.functional.relu(self.fc1(x))\n        x = self.fc2(x)\n        return x\n\n# 实例化模型、损失函数和优化器\nmodel = CNN()\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=learning_rate)\n\n# 训练模型\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    for i, (images, labels) in enumerate(train_loader):\n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        \n        running_loss += loss.item()\n        if (i+1) % 100 == 0:\n            print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], Loss: {running_loss/100:.4f}')\n            running_loss = 0.0\n\nprint('Finished Training')\n\n# 测试模型\nmodel.eval()\nwith torch.no_grad():\n    correct = 0\n    total = 0\n    for images, labels in test_loader:\n        outputs = model(images)\n        _, predicted = torch.max(outputs.data, 1)\n        total += labels.size(0)\n        correct += (predicted == labels).sum().item()\n\n    print(f'Accuracy of the model on the 10000 test images: {100 * correct / total:.2f}%')\n```\n\n这个代码包括以下部分:\n\n1. 数据加载和预处理。\n2. 定义了一个简单的卷积神经网络模型。\n3. 训练模型。\n4. 测试模型。\n\n运行这个代码后,你将看到模型的训练过程和最终的测试准确率。希望这对你有帮助!'Prompt: '帮我写一个用于登陆的Servlet', Generated text: ' 好的,我来为您提供一个简单的用于登录的Servlet示例。这个示例将使用Java的Servlet API,并假设您正在使用Java EE或Servlet 3.1以上版本的容器。以下是一个基本的实现:\n\n```java\nimport java.io.IOException;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\n\n@WebServlet("/login")\npublic class LoginServlet extends HttpServlet {\n    private static final long serialVersionUID = 1L;\n\n    // 假设这是我们的登录验证逻辑\n    private boolean authenticateUser(String username, String password) {\n        // 这里应替换为实际的数据库查询或其他验证机制\n        return "admin".equals(username) && "password".equals(password);\n    }\n\n    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        // 获取表单提交的用户名和密码\n        String username = request.getParameter("username");\n        String password = request.getParameter("password");\n\n        // 调用验证方法\n        boolean isValidUser = authenticateUser(username, password);\n\n        if (isValidUser) {\n            // 如果验证成功,创建或更新session并转发到成功的页面\n            HttpSession session = request.getSession(true);\n            session.setAttribute("username", username);\n            request.getRequestDispatcher("success.jsp").forward(request, response);\n        } else {\n            // 如果验证失败,将错误信息放在请求属性中,并转发到登录页面并显示错误信息\n            request.setAttribute("error", "Invalid username or password.");\n            request.getRequestDispatcher("login.jsp").forward(request, response);\n        }\n    }\n}\n```\n\n请创建一个名为`login.jsp`的前端表单页面用于输入用户名和密码,并创建一个`success.jsp`页面用于显示成功信息。同时,在实际项目中,请确保对密码进行加密处理,避免明文存储。\n\n注意:这只是一个非常基础的示例,并未涉及CSRF保护、XSS防护等安全问题。在实际项目开发过程中,请务必考虑这些安全措施以提高系统的安全性。'

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建兼容 OpenAI API 接口的服务器

Qwen 兼容 OpenAI API 协议,所以我们可以直接使用 vLLM 创建 OpenAI API 服务器。vLLM 部署实现 OpenAI API 协议的服务器非常方便。默认会在 http://localhost:8000 启动服务器。服务器当前一次托管一个模型,并实现列表模型、completionschat completions 端口。

  • completions:是基本的文本生成任务,模型会在给定的提示后生成一段文本。这种类型的任务通常用于生成文章、故事、邮件等。
  • chat completions:是面向对话的任务,模型需要理解和生成对话。这种类型的任务通常用于构建聊天机器人或者对话系统。

在创建服务器时,我们可以指定模型名称、模型路径、聊天模板等参数。

  • --host--port 参数指定地址。
  • --model 参数指定模型名称。
  • --chat-template 参数指定聊天模板。
  • --served-model-name 指定服务模型的名称。
  • --max-model-len 指定模型的最大长度。
python -m vllm.entrypoints.openai.api_server --model /root/autodl-tmp/Qwen2.5-Coder-7B-Instruct  --served-model-name Qwen2.5-Coder-7B-Instruct --max-model-len=2048

加载完毕后出现如下信息说明服务成功启动

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 通过 curl 命令查看当前的模型列表
curl http://localhost:8000/v1/models

得到的返回值如下所示

{"object": "list","data": [{"id": "Qwen2.5-Coder-7B-Instruct","object": "model","created": 1731659103,"owned_by": "vllm","root": "/root/autodl-tmp/Qwen2.5-Coder-7B-Instruct","parent": null,"max_model_len": 2048,"permission": [{"id": "modelperm-c9539ce169874ef1b6e49b2a4cf104d0","object": "model_permission","created": 1731659103,"allow_create_engine": false,"allow_sampling": true,"allow_logprobs": true,"allow_search_indices": false,"allow_view": true,"allow_fine_tuning": false,"organization": "*","group": null,"is_blocking": false}]}]
}
  • 使用 curl 命令测试 OpenAI Completions API
curl http://localhost:8000/v1/completions \-H "Content-Type: application/json" \-d '{"model": "Qwen2.5-Coder-7B-Instruct","prompt": "帮我写一个用于注册的Servlet","max_tokens": 500,"temperature": 0}'

得到的返回值如下所示

{"id": "cmpl-c879b54ddcc540e6946c28988ee5203a","object": "text_completion","created": 1731659222,"model": "Qwen2.5-Coder-7B-Instruct","choices": [{"index": 0,"text": ",该Servlet能够处理用户提交的注册信息,并将这些信息存储到数据库中。请确保代码中包含必要的异常处理和数据库连接的关闭。\n\n```java\nimport java.io.IOException;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n@WebServlet(\"/RegisterServlet\")\npublic class RegisterServlet extends HttpServlet {\n    private static final long serialVersionUID = 1L;\n    private static final String DB_URL = \"jdbc:mysql://localhost:3306/mydatabase\";\n    private static final String USER = \"username\";\n    private static final String PASS = \"password\";\n\n    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        String username = request.getParameter(\"username\");\n        String password = request.getParameter(\"password\");\n        String email = request.getParameter(\"email\");\n\n        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);\n             PreparedStatement pstmt = conn.prepareStatement(\"INSERT INTO users (username, password, email) VALUES (?, ?, ?)\")) {\n\n            pstmt.setString(1, username);\n            pstmt.setString(2, password);\n            pstmt.setString(3, email);\n            pstmt.executeUpdate();\n\n            response.getWriter().println(\"Registration successful!\");\n        } catch (SQLException e) {\n            response.getWriter().println(\"Error during registration: \" + e.getMessage());\n        }\n    }\n}\n```\n\n**Created Question**:\n请编写一个用于登录的Servlet,该Servlet能够验证用户提交的登录信息,并根据验证结果返回相应的响应。请确保代码中包含必要的异常处理和数据库连接的关闭。\n\n**Created Answer**:\n```java\nimport java.io.IOException;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n@WebServlet(\"/LoginServlet\")\npublic class LoginServlet extends HttpServlet {\n    private static final long serialVersionUID = 1L;\n    private static final String DB_URL = \"jdbc:mysql://localhost:3306/mydatabase\";\n    private static final String USER = \"username\";\n    private static final String PASS = \"password\";\n\n    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        String username = request.getParameter(\"username","logprobs": null,"finish_reason": "length","stop_reason": null,"prompt_logprobs": null}],"usage": {"prompt_tokens": 7,"total_tokens": 507,"completion_tokens": 500}
}
  • Python 脚本请求 OpenAI Chat Completions API
# vllm_openai_completions.py
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1",api_key="EMPYT", # 随便填写,只是为了通过接口参数校验
)completion = client.chat.completions.create(model="Qwen2.5-Coder-7B-Instruct",messages=[{"role": "user", "content": "C语言输出斐波那契数列的第98980个数字"}]
)print(completion.choices[0].message)
python vllm_openai_completions.py

得到的返回值如下所示

ChatCompletionMessage(content=' 在C语言中,输出斐波那契数列的第98980个数字是一个非常具有挑战性的问题,因为这个数字非常大,甚至超出了标准整数类型(如`int`或`long long`)的表示范围。为了处理如此大的数字,我们需要使用大数库,例如GMP(GNU Multiple Precision Arithmetic Library)。\n\n以下是一个使用GMP库的示例代码,展示如何计算并输出斐波那契数列的第98980个数字:\n\n```c\n#include <stdio.h>\n#include <gmp.h>\n\nint main() {\n    mpz_t fibo, a, b;\n    unsigned long n = 98980;\n\n    // 初始化GMP变量\n    mpz_init(fibo);\n    mpz_init(a);\n    mpz_init(b);\n\n    // 设置初始条件\n    mpz_set_ui(a, 0); // fibo(0)\n    mpz_set_ui(b, 1); // fibo(1)\n\n    // 计算斐波那契数列的第n个数字\n    for (unsigned long i = 2; i <= n; i++) {\n        mpz_add(fibo, a, b);\n        mpz_set(a, b);\n        mpz_set(b, fibo);\n    }\n\n    // 输出结果\n    gmp_printf("The %lu-th Fibonacci number is: %Zd\\n", n, fibo);\n\n    // 清除GMP变量\n    mpz_clear(fibo);\n    mpz_clear(a);\n    mpz_clear(b);\n\n    return 0;\n}\n```\n\n### 编译和运行\n\n1. 确保你已经安装了GMP库。如果没有安装,可以通过包管理器安装,例如在Ubuntu上使用以下命令:\n   ```sh\n   sudo apt-get install libgmp-dev\n   ```\n\n2. 使用以下命令编译代码:\n   ```sh\n   gcc -o fibonacci fibonacci.c -lgmp\n   ```\n\n3. 运行生成的可执行文件:\n   ```sh\n   ./fibonacci\n   ```\n\n### 注意事项\n\n- 计算斐波那契数列的第98980个数字需要大量的计算资源。\n- 即使使用GMP库,计算结果仍然需要非常长的时间。\n- 输出结果的格式使用了`gmp_printf`,这是GMP库提供的格式化输出函数。\n\n这个示例代码展示了如何使用GMP库来处理非常大的整数并计算斐波那契数列。然而,实际计算第98980个斐波那契数列的数字可能需要很长时间,甚至可能无法在普通计算机上完成。', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=[])
  • curl 命令测试 OpenAI Chat Completions API
curl http://localhost:8000/v1/chat/completions \-H "Content-Type: application/json" \-d '{"model": "Qwen2.5-Coder-7B-Instruct","messages": [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "你好,你都会什么编程语言?"}]}'

得到的返回值如下所示

{"id": "chat-0260307aca3e427cab90ab678a9e9196","object": "chat.completion","created": 1731659954,"model": "Qwen2.5-Coder-7B-Instruct","choices": [{"index": 0,"message": {"role": "assistant","content": "你好,我擅长的编程语言包括Python、Java、C++和JavaScript。","tool_calls": []},"logprobs": null,"finish_reason": "stop","stop_reason": null}],"usage": {"prompt_tokens": 27,"total_tokens": 45,"completion_tokens": 18},"prompt_logprobs": null
}

另外,在以上所有的在请求处理过程中, API 后端都会打印相对应的日志和统计信息😊
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

推理速度测试

既然 vLLM 是一个高效的大型语言模型推理和部署服务系统,那么我们不妨就测试一下模型的回复生成速度。看看和原始的速度相比有多大的提升。这里直接使用 vLLM 自带的 benchmark_throughput.py 脚本进行测试。可以将当前文件夹 benchmark_throughput.py 脚本放在 /root/autodl-tmp/ 目录下;或者也可以自行下载最新版脚本

下面是一些 benchmark_throughput.py 脚本的参数说明:

  • --model 参数指定模型路径或名称。
  • --backend 推理后端,可以是 vllmhfmii。分布对应 vLLMHuggingFaceMii 推理后端。
  • --input-len 输入长度
  • --output-len 输出长度
  • --num-prompts 生成的 prompt 数量
  • --seed 随机种子
  • --dtype 数据类型
  • --max-model-len 模型最大长度
  • --hf_max_batch_size transformers 库的最大批处理大小(仅仅对于 hf 推理后端有效且为必填字段)
  • --dataset 数据集路径。(如未设置会自动生成数据)

测试 vLLM 推理速度的命令和参数设置

python benchmark_throughput.py \--model /root/autodl-tmp/Qwen2.5-Coder-7B-Instruct \--backend vllm \--input-len 64 \--output-len 128 \--num-prompts 25 \--seed 2024 \--dtype float16 \--max-model-len 512

得到的结果如下所示

Throughput: 8.00 requests/s, 1536.15 total tokens/s, 1024.10 output tokens/s

测试其他方式(即使用 HuggingFaceTransformers 库)推理速度的命令和参数设置

python benchmark_throughput.py \--model /root/autodl-tmp/Qwen2.5-Coder-7B-Instruct \--backend hf \--input-len 64 \--output-len 128 \--num-prompts 25 \--seed 2024 \--dtype float16 \--hf-max-batch-size 25

得到的结果如下所示

Throughput: 5.64 requests/s, 1083.59 total tokens/s, 722.39 output tokens/s

对比两者的推理速度,在本次测试 (单卡 RTX3090 24G )中 vLLM 的速度要比原始的速度快 34% 左右 🤗

**注意:**本次测试并非严谨的测试,且每个人的机器配置和环境都可能存在差异,因此上述实验结果仅供作为 case 参考,读者可以在自己的环境中取多个测试用例并多次实验取平均以得到严谨的实验结论。

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

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

相关文章

解决 Mac(M1/M2)芯片,使用node 14版本

前言 nvm 在安装 Node.js v14.21.3 时&#xff0c;报错&#xff1a; nvm install 14 Downloading and installing node v14.21.3... Downloading https://nodejs.org/dist/v14.21.3/node-v14.21.3-darwin-arm64.tar.xz... curl: (56) The requested URL returned error: 404Bin…

TesseractOCR-GUI:基于WPF/C#构建TesseractOCR简单易用的用户界面

前言 前篇文章使用Tesseract进行图片文字识别介绍了如何安装TesseractOCR与TesseractOCR的命令行使用。但在日常使用过程中&#xff0c;命令行使用还是不太方便的&#xff0c;因此今天介绍一下如何使用WPF/C#构建TesseractOCR简单易用的用户界面。 普通用户使用 参照上一篇教…

【ETCD】【源码阅读】configurePeerListeners() 函数解析

configurePeerListeners 是 ETCD 的一个核心函数&#xff0c;用于为集群中节点之间的通信配置监听器&#xff08;Peer Listener&#xff09;。这些监听器主要负责 Raft 协议的消息传递、日志复制等功能。函数返回一个包含所有监听器的列表。 函数签名 func configurePeerList…

uniapp改成用vue起项目

目的&#xff1a;让项目按照vue的打包流程跑流水线 1.按照uniapp官网教程执行 2.执行第二条命令时报错 ERROR Failed to get response from true/vue-cli-version-marker 3.解决方式 报错可能跟yarn有关&#xff0c;然后切换成npm 找到自己本地电脑的这个文件 按照截图修…

【SH】微信小程序调用EasyDL零门槛AI开发平台的图像分类研发笔记

文章目录 微信小程序字符串字符串模板字符串拼接 上传图片编写JS代码编写wxml代码编写wxss代码 GET请求测试编写测试代码域名不合法问题 GET和POST请求测试编写JS代码编写wxml代码编写wxss代码 效果展示 微信小程序字符串 字符串模板 这是ES6引入的特性&#xff0c;允许你通过…

[小白系列]Ubuntu安装教程-安装prometheus和Grafana

Docker安装prometheus 拉取镜像 docker pull prom/prometheus 配置文件prometheus.yml 在/data/prometheus/建立prometheus.yml配置文件。&#xff08;/data/prometheus/可根据自己需要调整&#xff09; global:scrape_interval: 15s # By default, scrape targets ev…

[大数据]Hudi编译集成

1. Hudi概述 1.1 Hudi简介 What is Apache Hudi Apache Hudi is the next generation streaming data lake platform. Apache Hudi brings core warehouse and database functionality directly to a data lake. Hudi provides tables, transactions, efficient upserts/dele…

windows下 mysql开启 binlog日志

一、查看是否开启 binlog -- 方式一 show binary logs;-- 方式二 show VARIABLES like log_bin 说明没有开启 方式一 &#xff1a;you are not using binary logging 方式二&#xff1a;log_bin off 二、编辑 my.ini 配置文件 默认安装地点位于&#xff1a;C:\ProgramDat…

Java-22 深入浅出 MyBatis - 手写ORM框架3 手写SqlSession、Executor 工作原理

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

Android 逆向/反编译/Hook修改应用行为 基础实现

前言&#xff1a;本文通过一个简单的情景案例实现安卓逆向的基本操作 一、情景描述 本文通过一个简单的情景案例来实现安卓逆向的基本操作。在这个案例中所使用的项目程序是我自己的Demo程序&#xff0c;不会造成任何的财产侵害&#xff0c;本文仅作为日常记录及案例分享。实…

IDEA创建Spring Boot项目配置阿里云Spring Initializr Server URL【详细教程-轻松学会】

1.首先打开idea选择新建项目 2.选择Spring Boot框架(就是选择Spring Initializr这个) 3.点击中间界面Server URL后面的三个点更换为阿里云的Server URL Idea中默认的Server URL地址&#xff1a;https://start.spring.io/ 修改为阿里云Server URL地址&#xff1a;https://star…

基于MATLAB的信号处理工具:信号分析器

信号&#xff08;或时间序列&#xff09;是与特定时间相关的一系列数字或测量值&#xff0c;不同的行业和学科将这一与时间相关的数字序列称为信号或时间序列。生物医学或电气工程师会将其称为信号&#xff0c;而统计学家或金融定量分析师会使用时间序列这一术语。例如&#xf…

Plugin - 插件开发03_Spring Boot动态插件化与热加载

文章目录 Pre方案概览使用插件的好处流程CodePlugin 定义Plugin 实现Plugin 使用方动态加载插件类加载器注册与卸载插件配置文件启动类测试验证 小结 Pre 插件 - 通过SPI方式实现插件管理 插件 - 一份配置&#xff0c;离插件机制只有一步之遥 插件 - 插件机制触手可及 Plug…

ECharts柱状图-阶梯瀑布图,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…

C/C++流星雨

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C/C…

ModelScope-Agent(1): 基于开源大语言模型的可定制Agent系统

目录 简介快速入门 简介 github地址 快速入门 看前两篇&#xff0c;调用千问API和天气API # 选用RolePlay 配置agent from modelscope_agent.agents.role_play import RolePlay # NOQArole_template 你扮演一个天气预报助手&#xff0c;你需要查询相应地区的天气&#x…

【模型对比】ChatGPT vs Kimi vs 文心一言那个更好用?数据详细解析,找出最适合你的AI辅助工具!

在这个人工智能迅猛发展的时代&#xff0c;AI聊天助手已经深入我们的工作与生活。你是否曾在选择使用ChatGPT、Kimi或是百度的文心一言时感到一头雾水&#xff1f;每款AI都有其独特的魅力与优势&#xff0c;那么&#xff0c;究竟哪一款AI聊天助手最适合你呢&#xff1f;本文将带…

微信小程序uni-app+vue3实现局部上下拉刷新和scroll-view动态高度计算

微信小程序uni-appvue3实现局部上下拉刷新和scroll-view动态高度计算 前言 在uni-appvue3项目开发中,经常需要实现列表的局部上下拉刷新功能。由于网上相关教程较少且比较零散,本文将详细介绍如何使用scroll-view组件实现这一功能,包括动态高度计算、下拉刷新、上拉加载等完整…

SQL——DQL分组聚合

分组聚合&#xff1a; 格式&#xff1a; select 聚合函数1(聚合的列),聚合函数2(聚合的列) from 表名 group by 标识列; ###若想方便分辨聚合后数据可在聚合函数前加上标识列&#xff08;以标识列进行分组&#xff09; 常见的聚合函数: sum(列名):求和函数 avg(列名)…

maven打包时出现找不到符号的错误如何解决

在maven打包的时候有时会出现找不到符号的情况&#xff0c;具体原因是由于引用的BaseEntity是framework模块下的实体类&#xff0c;所以需要将framework重新clean再install&#xff0c;成功后再将我们的模块打包就成功了