当前位置: 首页 > news >正文

开源项目介绍:Native-LLM-for-Android

项目地址:Native-LLM-for-Android
创作活动时间:2025年

支持在 Android 设备上运行大型语言模型 (LLM) ,具体支持的模型包括:
DeepSeek-R1-Distill-Qwen: 1.5B
Qwen2.5-Instruct: 0.5B, 1.5B
Qwen2/2.5VL: 2B, 3B
MiniCPM-DPO/SFT: 1B, 2.7B
Gemma2-it: 2B
Phi3.5-mini-instruct: 3.8B
Llama-3.2-Instruct: 1B

Native-LLM-for-Android项目主要提供2个参考点,1、将LLM模型导出为onnx模型,2、在安卓端实现LLL模型的运行,本博文主要关注将llm导出为onnx推理(对现有的llm模型进行局部修改并导出),并以miniCPM模型为例进行测试。同时,Native-LLM-for-Android项目还有一些列模型量化代码可以学习。

1、模型运行性能

运行最快的模型是Llama3.2-1B-Instruct q8f32,达到25 token每秒,相应的硬件与os为 Nubia Z50(Android 13、8_Gen2-CPU);其次是Distill-Qwen-1.5B q8f32,达到22 token每秒,相应的硬件与os为Xiaomi-14T-Pro (HyperOS 2、MediaTek_9300±CPU);

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2、核心功能

这里主要关注将llm导出为onnx脱离torch环境运行,因此对Android运行代码不予理会

2.1、分词器

分词器也就是Tokenizer ,一共两个功能:
1、将输入模型的文本,分为多个短词,并转换为token,
2、将模型输出的token转换为文本
需要注意的是,不同的llm模型分词规则是不一样的,同时对于的token编码规则也不同

一般运行onnx模型,都是基于Transformer库中的Tokenizer,这无法脱离torch环境。应该自行实现。

Native-LLM-for-Android项目中Tokenizer 依赖的是mnn-llm仓库中的实现.
具体代码链接为:
https://github.com/wangzhaode/mnn-llm/blob/master/src/tokenizer.cpp,是纯c++代码,与torch环境毫无关联

同时,在每一种模型的Android-onnx代码路径下,都有对于的Tokenizer的c++实现代码
在这里插入图片描述

2.2、导出onnx模型

在Native-LLM-for-Android项目下Export_ONNX目录中,每一个模型都有单独的导出代码
在这里插入图片描述
如Gemma模型的导出,分别执行A-B-C步骤,导出3个模型,在最后的导出代码中含onnx推理代码
在这里插入图片描述

其中关于QwenVL模型的导出较为复杂,需要对transformers库中modeling_qwen2_vl.py文件进行改写覆盖,将单个模型拆分为5个模型运行。其中A模型是VIT的主体部分,E模型是llm的主体部分,BCD模型是一些切片索引操作,被单独导出为模型。关于E模型导出有报错,可以参考https://github.com/DakeQQ/Native-LLM-for-Android/issues/10
在这里插入图片描述

如果导出模型报错

RuntimeError: The serialized model is larger than the 2GiB limit imposed by the protobuf library. Therefore the output file must be a file path, so that the ONNX external data can be written to the same directory. Please specify the output file name.

则尝试将torch版本降低到2.4.1
pip install torch2.4.1 torchvision0.19.1 torchaudio==2.4.1 --index-url https://download.pytorch.org/whl/cu121

2.3、onnx模型量化

关于onnx模型量化,可以参考:https://blog.csdn.net/m0_63642362/article/details/124741589,根据介绍,onnx量化可以分为动态量化与静态量化,动态量化在推理时根据输入数据动态计算缩放因子与零点;静态量化,使用校准数据集离线计算缩放因子(Scale)和零点(Zero Point)。通常,建议对 RNN 和基于 Transformer 的模型使用动态量化,对 CNN 模型使用静态量化

在Native-LLM-for-Android-main\Do_Quantize\Dynamic_Quant 目录下有多个模型量化代码,具体如下图所示
在这里插入图片描述
q8_f16的量化代码如下所示,可以看到对于大尺寸的模型的量化有一个关键参数项 is_large_model

import os
import gc
import glob
import sys
import onnx
import torch
import subprocess
import onnx.version_converter
from onnxsim import simplify
from onnxslim import slim
from onnxruntime.quantization import QuantType, quantize_dynamic
from onnxruntime.transformers.optimizer import optimize_model
from transformers import AutoModelForCausalLM# Path Setting
original_folder_path = r"C:\Users\Downloads\Model_ONNX"                          # The original folder.
quanted_folder_path = r"C:\Users\Downloads\Model_ONNX_Optimized"                 # The optimized folder.
model_path = os.path.join(original_folder_path, "Model.onnx")                    # The original fp32 model path.
quanted_model_path = os.path.join(quanted_folder_path, "Model_Optimized.onnx")   # The optimized model stored path.
download_path = r'C:\Users\Downloads\Qwen2-1.5B-Instruct'                        # Set the folder path where the LLM whole project downloaded, otherwise set "NONE".
use_gpu = True                                                                   # If true, the transformers.optimizer will remain the FP16 processes.
provider = 'CPUExecutionProvider'                                                # ['CPUExecutionProvider', 'CUDAExecutionProvider']
use_low_memory_mode_in_Android = False                                           # If you need to use low memory mode on Android, please set it to True.# Preprocess, it also cost alot of memory during preprocess, you can close this command and keep quanting. Call subprocess may get permission failed on Windows system.
# (optional process)
# subprocess.run([f'python -m onnxruntime.quantization.preprocess --auto_merge --all_tensors_to_one_file --input {model_path} --output {quanted_folder_path}'], shell=True)# Start Quantize
quantize_dynamic(model_input=model_path,model_output=quanted_model_path,per_channel=True,                                        # True for model accuracy but cost a lot of time during quanting process.reduce_range=False,                                      # True for some x86_64 platform.weight_type=QuantType.QInt8,                            # It is recommended using uint8 + Symmetric Falseextra_options={'ActivationSymmetric': False,             # True for inference speed. False may keep more accuracy.'WeightSymmetric': False,                 # True for inference speed. False may keep more accuracy.'EnableSubgraph': True,                   # True for more quant.'ForceQuantizeNoInputCheck': False,       # True for more quant.'MatMulConstBOnly': True                  # False for more quant. Sometime, the inference speed may get worse.},nodes_to_exclude=None,                                   # Specify the node names to exclude quant process. Example: nodes_to_exclude={'/Gather'}use_external_data_format=True                            # Save the model into two parts.
)model_size_bytes = sys.getsizeof(onnx.load(model_path).SerializeToString())
model_size_gb = model_size_bytes * 9.31322575e-10            # 1 / (1024 * 1024 * 1024)
if model_size_gb > 2.0:is_large_model = True
else:is_large_model = True if use_low_memory_mode_in_Android else False# ONNX Model Optimizer
slim(model=quanted_model_path,output_model=quanted_model_path,no_shape_infer=False,   # True for more optimize but may get errors.skip_fusion_patterns=False,no_constant_folding=False,save_as_external_data=is_large_model,verbose=False
)if download_path == "NONE":num_heads = 0    # defaulthidden_size = 0  # default
else:if ('vl' in download_path.lower()) & ('qwen' in download_path.lower()):if "2.5" in download_path or "3b" in download_path.lower():from transformers import Qwen2_5_VLForConditionalGenerationmodel = Qwen2_5_VLForConditionalGeneration.from_pretrained(download_path, torch_dtype=torch.float16, device_map='cpu', trust_remote_code=True, low_cpu_mem_usage=True).eval()else:from transformers import Qwen2VLForConditionalGenerationmodel = Qwen2VLForConditionalGeneration.from_pretrained(download_path, torch_dtype=torch.float16, device_map='cpu', trust_remote_code=True, low_cpu_mem_usage=True).eval()else:model = AutoModelForCausalLM.from_pretrained(download_path, torch_dtype=torch.float16, device_map='cpu', trust_remote_code=True, low_cpu_mem_usage=True).eval()num_heads = model.config.num_attention_headshidden_size = model.config.hidden_sizedel modelgc.collect()# transformers.optimizer
model = optimize_model(quanted_model_path,use_gpu=use_gpu,opt_level=2,num_heads=num_heads,hidden_size=hidden_size,provider=provider,verbose=False,model_type='bert')
model.convert_float_to_float16(keep_io_types=True,force_fp16_initializers=True,use_symbolic_shape_infer=True,  # True for more optimize but may get errors.op_block_list=['DynamicQuantizeLinear', 'DequantizeLinear', 'DynamicQuantizeMatMul', 'Range', 'MatMulIntegerToFloat']
)
model.save_model_to_file(quanted_model_path, use_external_data_format=is_large_model)
del model
gc.collect()# onnxslim 2nd
slim(model=quanted_model_path,output_model=quanted_model_path,no_shape_infer=False,   # True for more optimize but may get errors.skip_fusion_patterns=False,no_constant_folding=False,save_as_external_data=is_large_model,verbose=False
)# Upgrade the Opset version. (optional process)
model = onnx.load(quanted_model_path)
model = onnx.version_converter.convert_version(model, 21)
onnx.save(model, quanted_model_path, save_as_external_data=is_large_model)if is_large_model:pattern = os.path.join(quanted_folder_path, '*.data')files_to_delete = glob.glob(pattern)for file_path in files_to_delete:try:os.remove(file_path)except Exception as e:print(f"Error deleting {file_path}: {e}")# It is not recommended to convert an FP16 ONNX model to the ORT format because this process adds a Cast operation to convert the FP16 process back to FP32.

3、导出minicpm模型onnx推理

3.1 下载模型

pip install modelscope

基于modelscope 库可以下载MiniCPM-2B-dpo-fp16模型

from modelscope import snapshot_download
model_dir = snapshot_download('OpenBMB/MiniCPM-2B-dpo-fp16',cache_dir=".cache_dir")

3.2 导出onnx模型

这里以MiniCPM-2B-split导出方式为例

先在命令行进入 F:\Native-LLM-for-Android-main\Export_ONNX\MiniCPM\MiniCPM-2B-split 目录

然后创建,model_a,model_b两个目录,用于存储2个onnx模型,并将代码修改为以下形式
在这里插入图片描述

最后在命令行中执行 python .\MiniCPM_Export.py 即可实现模型导出为onnx,并进行推理测试
在这里插入图片描述
这里可以发现代码的推理速度居然为0.375token/s,简直巨慢。

按照单个模型导出,并进行推理测试,发现效果如下所示,可以发现性能有6倍的提升,这表明数据通信也占据了大量的耗时。
在这里插入图片描述

3.3 单独运行onnx

基于以下代码可以运行onnx模型,但无法脱离transformers库,除非手写tokenizer实现分词,并实现token与文本的对应关系。


import numpy as np
import onnxruntime
from transformers import AutoModelForCausalLM, AutoTokenizer
import timepath = 'F:\DMT\.cache_dir\OpenBMB\MiniCPM-2B-dpo-fp16'  # Set the folder path where the MiniCPM whole project downloaded.
onnx_model_A = r'F:\Native-LLM-for-Android-main\Export_ONNX\MiniCPM\MiniCPM-2B-single\model_q8_f16\MiniCPM_part_A_Optimized.onnx'  # Assign a path where the exported MiniCPM_part_A stored.# Run the exported model by ONNX Runtime
query = "山东省最高的山是哪座山, 它比黄山高还是矮?差距多少?"
max_seq_len = 1024  # Please modify the same variable, which declared in the modified modeling_minicpm.py on line 1008, at the same time.
num_heads = 36
head_dim = 64
num_key_value_heads = 36
num_layers = 40
hidden_size = 2304max_single_chat_length = 341  # It a adjustable value, but must less than max_seq_len.
tokenizer = AutoTokenizer.from_pretrained(path, trust_remote_code=True)# ONNX Runtime settings
session_opts = onnxruntime.SessionOptions()
session_opts.log_severity_level = 3  # error level, it a adjustable value.
session_opts.inter_op_num_threads = 0  # Run different nodes with num_threads. Set 0 for auto.
session_opts.intra_op_num_threads = 0  # Under the node, execute the operators with num_threads. Set 0 for auto.
session_opts.enable_cpu_mem_arena = True  # True for execute speed; False for less memory usage.
session_opts.execution_mode = onnxruntime.ExecutionMode.ORT_SEQUENTIAL
session_opts.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_ALL
session_opts.add_session_config_entry("session.intra_op.allow_spinning", "1")
session_opts.add_session_config_entry("session.inter_op.allow_spinning", "1")ort_session_A = onnxruntime.InferenceSession(onnx_model_A, sess_options=session_opts, providers=['CPUExecutionProvider'])
in_name_A = ort_session_A.get_inputs()
out_name_A = ort_session_A.get_outputs()
in_name_A0 = in_name_A[0].name
in_name_A1 = in_name_A[1].name
in_name_A2 = in_name_A[2].name
in_name_A3 = in_name_A[3].name
in_name_A4 = in_name_A[4].name
in_name_A5 = in_name_A[5].name
out_name_A0 = out_name_A[0].name
out_name_A1 = out_name_A[1].name
out_name_A2 = out_name_A[2].name# Pre-process inputs
prompt = tokenizer.apply_chat_template([{"role": 'user', "content": query}], tokenize=False, add_generation_prompt=False)
token = tokenizer(prompt, return_tensors='pt')['input_ids']
ids_len = token.shape[1] + np.zeros(1, dtype=np.int64)
input_ids = np.zeros(max_seq_len, dtype=np.int32)
input_ids[:ids_len[0]] = token[0, :]
attention_mask = np.array([-65504.0], dtype=np.float32)
history_len = np.zeros(1, dtype=np.int64)
past_key_states_A = np.zeros((num_layers, num_key_value_heads, max_seq_len, head_dim), dtype=np.float16)
past_values_states_A = past_key_states_A
num_decode = 0
print('\nTest Question: ' + query + "\n\nMiniCPM Answering:\n")# Start to run LLM
start_time = time.time()
while history_len < max_single_chat_length:token_id, past_key_states_A, past_values_states_A = ort_session_A.run([out_name_A0, out_name_A1, out_name_A2],{in_name_A0: input_ids,in_name_A1: attention_mask,in_name_A2: past_key_states_A,in_name_A3: past_values_states_A,in_name_A4: history_len,in_name_A5: ids_len})if token_id == 2:  # the stop_id in MiniCPM is "2"breakelse:history_len[0] += ids_len[0]ids_len[0] = 1num_decode += 1attention_mask[0] = 0.0input_ids[0] = token_idprint(tokenizer.decode(token_id), end="", flush=True)
end_time = time.time()
print(f"\n\nDecode: {(num_decode / (end_time - start_time)):.3f} token/s")

相关文章:

开源项目介绍:Native-LLM-for-Android

项目地址&#xff1a;Native-LLM-for-Android 创作活动时间&#xff1a;2025年 支持在 Android 设备上运行大型语言模型 &#xff08;LLM&#xff09; &#xff0c;具体支持的模型包括&#xff1a; DeepSeek-R1-Distill-Qwen: 1.5B Qwen2.5-Instruct: 0.5B, 1.5B Qwen2/2.5VL:…...

vocabulary is from your listening,other speaking and your thought.

不要把单词放在自己的大脑里&#xff0c;放在自己的嘴巴里&#xff0c;自己在那疯狂重复的recite&#xff0c;its futile.只是单点记忆单词&#xff0c;记住也是temporary&#xff0c;而且是单点的记忆&#xff0c;当别人说此词汇&#xff0c;你也听不懂或分辨就是这个单词&…...

前端知识点---路由模式-实例模式和单例模式(ts)

在 ArkTS&#xff08;Ark UI 框架&#xff09;中&#xff0c;路由实例模式&#xff08;Standard Instance Mode&#xff09;主要用于管理页面跳转。当创建一个新页面时&#xff0c;可以选择标准实例模式&#xff08;Standard Mode&#xff09;或单实例模式&#xff08;Single M…...

Matplotlib库中color 参数颜色有多少种

**当我们绘图超过十几种颜色。我都是 定义颜色列表&#xff08; ** colors [blue, green, red, cyan, magenta, yellow, greenyellow, orange, purple, brown, pink, gray]1、 颜色名称 Matplotlib常用的颜色名称&#xff1a; red 或 r green 或 g blue 或 b yellow 或 y cy…...

LINUX虚拟机中,不能播放RTSP设备,怎么办

首先&#xff0c;主机能够打开RTSP设备。虚拟机无法打开。 虚拟机网络设置 桥接网卡&#xff0c;选择正确的网卡。 虚拟机IP设置 需要是同一个网段。交换机的设备是192.168.1.192 用ffplay测试...

宝塔的ssl文件验证域名后,会在域名解析列表中留下记录吗?

在使用宝塔面板进行SSL证书验证域名后&#xff0c;通常不会在域名解析列表中留下记录。验证过程中添加的TXT记录仅用于验证域名的所有权&#xff0c;一旦验证完成&#xff0c;就可以安全地删除这些记录&#xff0c;不会影响SSL证书的正常使用。根据搜索结果&#xff0c;DNS验证…...

mitt 依赖库详解

一、概述 mitt 是一个极其轻量级的 JavaScript 事件发射器库&#xff0c;实现了发布-订阅模式。该模式允许对象间松散耦合&#xff0c;一个对象&#xff08;发布者&#xff09;可以发布事件&#xff0c;而其他对象&#xff08;订阅者&#xff09;可以监听这些事件并作出响应。…...

OSPF网络类型:NBMA与P2MP

一、NBMA网络 NBMA网络的特点 连接方式&#xff1a; 支持多台设备连接到同一个网络段&#xff0c;但网络本身不支持广播或组播。典型例子&#xff1a;帧中继、ATM。 DR/BDR选举&#xff1a; 由于网络不支持广播&#xff0c;OSPF需要手动配置邻居。 仍然会选举DR&#xff08…...

VUE叉的工作原理?

Vuex 是 Vue.js 的一个专门用于状态管理的库&#xff0c;其工作原理基于单向数据流和集中式存储&#xff0c;旨在解决跨组件之间状态共享和管理的复杂性。以下是 Vuex 的核心工作原理及其关键组成部分&#xff1a; 核心概念 State&#xff08;状态&#xff09; Vuex 使用一个单…...

H.264语法结构分析之frame_cropping_flag

技术背景 开发者对接我们轻量级RTSP服务的时候&#xff0c;利用部分开源的播放器&#xff0c;播放流数据的时候&#xff0c;说分辨率不对&#xff0c;导致看到的图像有问题&#xff0c;用我们的player或常见的通用播放器&#xff0c;又都是好的&#xff0c;这就扯到了今天的主…...

【智能体】本地安装Conda和搭建OpenManus环境

整理不易&#xff0c;请不要令色你的赞和收藏。 1. 前言 没体验到 Manus&#xff1f;不妨使用 MetaGPT 开源的 OpenManus 搭建自己的 Manus。本文将带你安装 Conda 并搭建自己的 Manus。 2. 前提条件 已安装 conda&#xff0c;没安装的话&#xff0c;下文有介绍。 OpenManu…...

【linux网络编程】套接字编程API详细介绍

在C语言中&#xff0c;套接字&#xff08;Socket&#xff09;编程主要用于网络通信&#xff0c;尤其是在基于TCP/IP协议的应用程序开发中。常用的套接字编程API主要基于Berkeley Sockets&#xff08;伯克利套接字&#xff09;接口&#xff0c;这些函数通常在<sys/socket.h&g…...

杂项知识笔记搜集

1.pygame pygame可以画出来图形界面&#xff0c;pygame Python仓库 PyGame游戏编程_游戏程序设计csdn-CSDN博客 2.V4L2库 V4L2是Linux上的Camera采集器的框架 Video for Linux &#xff0c;是从Linux2.1版本开始支持的。HDMI视频采集卡采集到的视频通过USB3.0输出&#xff0…...

模型微调——模型性能提升方法及注意事项(自用)

名词补充 人为为训练数据标注的标签称为黄金标准或真实值&#xff0c;这个过程一定程度上保证训练的准确性&#xff0c;但是其人工标注的成本和时间很高&#xff0c;并且标注的标签受人的主观因素影响。 导致模型性能不佳的因素和解决办法 ①不同类别的数据不平衡&#xff1a;统…...

RabbitMQ之旅(1)

相信自己,终会成功 目录 主流MQ产品 1.kafaka 2.RocketMQ 3.RabbitMQ 在xshell上安装RabbitMQ RabbitMQ七种工作模式 1.简单模式 ​编辑 2.工作队列模式 3.发布/订阅模式 4.路由模式 5.通配符模式 6.RPC模式 AMQP.BasicProperties 设置消息属性的类 7.发布确认模…...

TCP7680端口是什么服务

WAF上看到有好多tcp7680端口的访问信息 于是上网搜索了一下&#xff0c;确认TCP7680端口是Windows系统更新“传递优化”功能的服务端口&#xff0c;个人理解应该是Windows利用这个TCP7680端口&#xff0c;直接从内网已经具备更新包的主机上共享下载该升级包&#xff0c;无需从微…...

跟着 Lua 5.1 官方参考文档学习 Lua (11)

文章目录 5.4.1 – PatternsCharacter Class:Pattern Item:Pattern:Captures: string.find (s, pattern [, init [, plain]])例子&#xff1a;string.find 的简单使用 string.match (s, pattern [, init])string.gmatch (s, pattern)string.gsub (s, pattern, repl [, n])例子&…...

<script setup>和export default { setup() { ... } }区别

在 Vue 3 组合式 API&#xff08;Composition API&#xff09;中&#xff0c;<script setup> 和 export default setup() {} 都用于定义组件的逻辑&#xff0c;但它们有一些重要的区别&#xff1a; 1️⃣ <script setup>&#xff08;推荐&#xff09; ✅ 更简洁、…...

leetcode hot100--动态规划【五步总纲】

五步&#xff1a; 1.dp数组以及下标定义 dp[i] 2.递推公式 dp[n]dp[n-1]dp[n-2] 3.dp数组如何初始化 注意&#xff1a;判断边界条件&#xff0c;n0dp[1]就不存在【斐波那契】 4.遍历顺序 for循环顺序 5.打印数组【debug】 第一题&#xff1a;斐波那契数列 首先回顾了…...

RtlLookupAtomInAtomTable函数分析之RtlpAtomMapAtomToHandleEntry函数的作用是验证其正确性

第一部分&#xff1a; NTSTATUS RtlLookupAtomInAtomTable( IN PVOID AtomTableHandle, IN PWSTR AtomName, OUT PRTL_ATOM Atom OPTIONAL ) { NTSTATUS Status; PRTL_ATOM_TABLE p (PRTL_ATOM_TABLE)AtomTableHandle; PRTL_ATOM_TABLE_ENTRY a; …...

【从零开始学习计算机科学】硬件设计与FPGA原理

硬件设计 硬件设计流程 在设计硬件电路之前,首先要把大的框架和架构要搞清楚,这要求我们搞清楚要实现什么功能,然后找找有否能实现同样或相似功能的参考电路板(要懂得尽量利用他人的成果,越是有经验的工程师越会懂得借鉴他人的成果)。如果你找到了的参考设计,最好还是…...

todo: 使用融云imserve做登录(android)

使用融云做登录注册思路 注册界面需要name, email, password考虑到融云注册用户的post格式 POST http://api.rong-api.com/user/getToken.json?userId1690544550qqcom&nameIronman这里的userId可以使用用户的email&#xff0c;但是要截断和 . 符号&#xff0c;即1690544…...

从0开始的操作系统手搓教程23:构建输入子系统——实现键盘驱动1——热身驱动

目录 所以&#xff0c;键盘是如何工作的 说一说我们的8042 输出缓冲区寄存器 状态寄存器 控制寄存器 动手&#xff01; 注册中断 简单整个键盘驱动 Reference ScanCode Table 我们下一步就是准备进一步完善我们系统的交互性。基于这个&#xff0c;我们想到的第一个可以…...

Azure云生态系统详解:核心服务、混合架构与云原生概念

核心服务&#xff1a;深入掌握Azure SQL Database、Azure Database for PostgreSQL、Azure Database for MySQL的架构、备份恢复、高可用性配置&#xff08;如Geo-Replication、自动故障转移组、异地冗余备份&#xff09;。混合架构&#xff1a;熟悉Azure Arc&#xff08;管理混…...

Unity Dots

文章目录 什么是DotsDOTS的优势ECS&#xff08;实体组件系统&#xff09;Job System作业系统Burst编译器最后 什么是Dots DOTS&#xff08;Data-Oriented Technology Stack&#xff09;是Unity推出的一种用于开发高性能游戏和应用的数据导向技术栈&#xff0c;包含三大核心组件…...

SAP DOI EXCEL宏的使用

OAOR里上传EXCEL模版 屏幕初始化PBO创建DOI EXCEL对象&#xff0c;并填充EXCEL内容 *&---------------------------------------------------------------------* *& Module INIT_DOI_DISPLAY_9100 OUTPUT *&--------------------------------------------…...

VSTO(C#)Excel开发3:Range对象 处理列宽和行高

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…...

单链表基本操作的实现与解析(补充)

目录 一、引言 二、代码实现 遍历考虑情况 三、操作解析 查找操作&#xff08;sltfind函数&#xff09; 前插操作&#xff08;sltinsert函数&#xff09; 后插操作&#xff08;sltinsertafter函数&#xff09; 前删操作&#xff08;slterase函数&#xff09; 后删操作&…...

电子学会—2024年月6青少年软件编程(图形化)四级等级考试真题——魔法门

魔法门 1.准备工作 (1)保留默认角色小猫和白色背景; (2)添加角色Home Button&#xff0c;复制9个造型&#xff0c;在每个造型上分别加上数字1到9&#xff0c;如下图所示; 2.功能实现 (1)程序开始&#xff0c;依次克隆出五个Home Button&#xff0c;克隆体之间的间距为90; …...

《加快应急机器人发展的指导意见》中智能化升级的思考——传统应急设备智能化升级路径与落地实践

感谢阅读本次内容分享&#xff0c;下面我将解读分析《加快应急机器人发展的指导意见》&#xff0c;喜欢的点赞支持一下呗~(日更真的很辛苦~)&#xff0c;欢迎评论区留言讨论&#xff0c;你们的发言我都会看到~ 《加快应急机器人发展的指导意见》中智能化升级的思考——传统应急…...

Git系列之git tag和ReleaseMilestone

以下是关于 Git Tag、Release 和 Milestone 的深度融合内容&#xff0c;并补充了关于 Git Tag 的所有命令、详细解释和指令实例&#xff0c;条理清晰&#xff0c;结合实际使用场景和案例。 1. Git Tag 1.1 定义 • Tag 是 Git 中用于标记特定提交&#xff08;commit&#xf…...

【每日学点HarmonyOS Next知识】Web上传文件、监听上下左右区域连续点击、折叠悬停、字符串相关、播放沙盒视频

1、HarmonyOS APP内h5原生webview input[typefile]无法唤醒手机上传&#xff1f; 文件上传要使用对应的picker https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/web-file-upload-V5 Web组件支持前端页面选择文件上传功能&#xff0c;应用开发者可以使用on…...

解决电脑问题(3)——显示器问题

当电脑显示器出现问题时&#xff0c;可以根据不同的故障现象采取相应的解决方法&#xff0c;以下是一些常见的情况及解决措施&#xff1a; 屏幕无显示 检查连接&#xff1a;首先检查显示器与电脑主机之间的视频连接线是否插好&#xff0c;确保两端的接口都牢固连接&#xff0c…...

AArch64架构及其编译器

—1.关于AArch64架构 AArch64是ARMv8-A架构的64位执行状态&#xff0c;支持高性能计算和大内存地址空间。它广泛应用于现代处理器&#xff0c;如苹果的A系列芯片、高通的Snapdragon系列&#xff0c;以及服务器和嵌入式设备。 • 编译器&#xff1a;可以使用GCC、Clang等编译器编…...

免费送源码:Java+springboot+MySQL 房屋租赁系统小程序的设计与实现 计算机毕业设计原创定制

目 录 摘要 1 1 绪论 1 1.1选题意义 1 1.2开发现状 1 1.3springboot框架介绍 1 1.4论文结构与章节安排 1 2 房屋租赁系统小程序系统分析 3 2.1 可行性分析 3 2.1.1 技术可行性分析 3 2.1.2 经济可行性分析 3 2.1.3 法律可行性分析 3 2.2 系统功能分析 3 2.2.1 功…...

前端数据模拟 Mock.js 学习笔记

mock.js介绍 Mock.js是一款前端开发中拦截Ajax请求再生成随机数据响应的工具&#xff0c;可以用来模拟服务器响应 优点是&#xff1a;非常方便简单&#xff0c;无侵入性&#xff0c;基本覆盖常用的接口数据类型支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜…...

【Linux内核系列】:深入解析输出以及输入重定向

&#x1f525; 本文专栏&#xff1a;Linux &#x1f338;作者主页&#xff1a;努力努力再努力wz ★★★ 本文前置知识&#xff1a; 文件系统以及文件系统调用接口 用c语言简单实现一个shell外壳程序 内容回顾 那么在此前的学习中&#xff0c;我们对于Linux的文件系统已经有了…...

Adam 优化器与动量法:二阶矩与 ODE 的联系

Adam 优化器与动量法&#xff1a;二阶矩与 ODE 的联系 作为深度学习研究者&#xff0c;你一定对 Adam&#xff08;Adaptive Moment Estimation&#xff09;优化器非常熟悉。它因自适应学习率和高效率而成为训练神经网络的标配算法。Adam 使用了一阶动量&#xff08;梯度的指数…...

嵌入式学习第二十三天--网络及TCP

进程通信的方式: 同一主机 传统 system V 不同主机 网络 --- 解决不同主机间 的进程间通信 网络 (通信) //1.物理层面 --- 联通(通路) //卫星 2G 3G 4G 5G 星链 (千帆) //2.逻辑层面 --- 通路(软件) MAC os LINUX …...

前端表单提交与后端处理全解析:从HTML到Axios与SpringBoot实战

前端表单提交与后端处理全解析:从HTML到Axios与SpringBoot实战 一、GET与POST请求的两种面孔 1. HTML表单基础实现 <!-- GET请求示例:搜索表单 --> <form action="/api/search" method="GET"><input type="text" name="…...

python django orm websocket html 实现deepseek持续聊天对话页面

最终效果&#xff1a; 技术栈&#xff1a; python django orm websocket html 项目结构&#xff1a; 这里只展示关键代码&#xff1a; File: consumers.py # -*- coding:utf-8 -*- # Author: 喵酱 # time: 2025 - 03 -02 # File: consumers.py # desc: import json from asg…...

大白话html语义化标签优势与应用场景

大白话html语义化标签优势与应用场景 大白话解释 语义化标签就是那些名字能让人一看就大概知道它是用来做什么的标签。以前我们经常用<div>来做各种布局&#xff0c;但是<div>本身没有什么实际的含义&#xff0c;就像一个没有名字的盒子。而语义化标签就像是有名…...

考研英语语法全攻略:从基础到长难句剖析​

引言 在考研英语的备考之旅中,语法犹如一座灯塔,为我们在浩瀚的英语知识海洋中指引方向。无论是阅读理解中复杂长难句的解读,还是写作时准确流畅表达的需求,扎实的语法基础都起着至关重要的作用。本文将结合有道考研语法基础入门课的相关内容,为大家全面梳理考研英语语法…...

Vue3 生命周期

回顾Vue2的生命周期 创建&#xff08;创建前&#xff0c;创建完毕&#xff09;beforeCreate、created挂载&#xff08;挂载前&#xff0c;挂载完毕&#xff09;beforeMount、mounted更新&#xff08;更新前&#xff0c;更新完毕&#xff09;beforeUpdate、updated销毁&#xf…...

hbase-05 namespace、数据的确界TTL

要点 掌握HBase的命名空间namespace概念 掌握HBase数据版本确界 掌握HBase数据TTL 1. HBase的namespace 1.1 namespace基本介绍 在HBase中&#xff0c;namespace命名空间指对一组表的逻辑分组&#xff0c;类似RDBMS中的database&#xff0c;方便对表在业务上划分。Apache…...

线程的常见使用方法

Java中的线程并不是真正意义的线程,我们使用的是Thread类来表示线程,而这个类是 JVM 用来管理线程的一个类,也就是说,每个线程都有一个唯一的 Thread对象 与之关联 每一个执行流都需要有一个对象来进行描述,那么一个Thread对象就是用来表述一个线程执行流的,JVM会将这些对象统…...

架构师面试(十一):消息收发

问题 IM 是互联网中非常典型的独立的系统&#xff0c;麻雀虽小但五脏俱全&#xff0c;非常值得深入研究和探讨&#xff0c;继上次IM相关题目之后&#xff0c;我们继续讨论IM相关话题。 关于IM系统【消息收发模型】的相关描述&#xff0c;下面说法错误的有哪几项&#xff1f; …...

MoonSharp 文档一

目录 1.Getting Started 步骤1&#xff1a;在 IDE 中引入 MoonSharp 步骤2&#xff1a;引入命名空间 步骤3&#xff1a;调用脚本 步骤4&#xff1a;运行代码 2.Keeping a Script around 步骤1&#xff1a;复现前教程所有操作 步骤2&#xff1a;改为创建Script对象 步骤…...

【linux网络编程】端口

一、端口&#xff08;Port&#xff09;概述 在计算机网络中&#xff0c;端口&#xff08;Port&#xff09; 是用来标识不同进程或服务的逻辑通信端点。它类似于一座大楼的房间号&#xff0c;帮助操作系统和网络协议区分不同的应用程序&#xff0c;以便正确地传输数据。 1. 端口…...

Vulnhub-Node

目录标题 一、靶机搭建二、信息收集靶机信息扫ip扫开放端口和版本服务信息指纹探测目录扫描 三、Web渗透信息收集zip爆破ssh连接 四、提权内核版本提权 利用信息收集拿到路径得到账户密码&#xff0c;下载备份文件&#xff0c;base64解密后&#xff0c;利用fcrackzip爆破zip压缩…...