cann/asc-devkit算子入图开发基本流程
基本开发流程【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit该开发流程以工程化算子开发为基础除了需要提供工程化算子开发中的算子实现文件外还需要额外交付算子入图的代码文件。本节仅提供算子入图代码文件的开发指导。假设下图是我们需要使用的网络模型您可能会想直接逐个算子调用根据输入tensor得到输出tensor就可以完成网络的运行但在图模式场景下实际的网络模型生成过程中会先进行tensor shape以及datatype的推导。这样可以让我们在图执行之前就知道各tensor的数据类型和形状提前校验其正确性同时提前推理出算子的输出张量描述包括张量的形状、数据类型及数据排布格式等信息算子构图准备阶段就可以为所有的张量静态分配内存避免动态内存分配带来的开销。下面的网络模型经过shape和datatype推导之后可以得到灰色底纹框中的推导信息图1shape与datatype推导示意图![](https://raw.gitcode.com/cann/asc-devkit/raw/c975c4a444b8d5c5dfc5201203324866d8a916d3/docs/zh/guide/figures/shape与datatype推导示意图.png shape与datatype推导示意图?utm_sourcegitcode_repo_files)除了tiling实现外算子入图时需要额外提供的实现代码有以下几种datatype推导根据算子的输入datatype、算子逻辑及算子属性等信息推理出算子的输出张量datatype。shape推导根据算子的输入shape、算子逻辑及算子属性等信息推理出算子的输出张量shape。ShapeRange推导编译时无法推导输出shape只能推导输出shape range执行完才能得出输出shape。在下发时需要按照输出shape range来申请最大输出内存该类算子需要提供ShapeRange推导函数。声明数据依赖部分算子在InferShape时需要依赖某个输入的具体值才可以进行这类算子被称为“数据依赖算子”对应的输入被称为“数据依赖输入”。该类算子在注册时需要声明其数据依赖输入。下表列出了不同类型的算子对上述实现代码的要求。表1不同的类型的算子对入图实现代码的要求分类对入图实现代码的要求根据输入shape可以推导出输出shape。shape推导datatype推导依赖输入的value才能推导出输出shape即数据依赖算子。如Reshape算子依赖shape输入的value才能推导出输出shape。shape推导datatype推导声明数据依赖编译时无法推导输出shape只能推导输出shape range执行完才能得出输出shape。Shape推导必选DataType推导必选ShapeRange推导必选声明数据依赖按需实际开发时通过固定的datatype和shape推导原型实现推导函数然后再通过SetInferShape、SetInferDataType接口来关联对应的shape推导函数样例如下。namespace ge { static graphStatus InferShape(gert::InferShapeContext *context) { ... return GRAPH_SUCCESS; } static graphStatus InferDataType(gert::InferDataTypeContext *context) { ... return ge::GRAPH_SUCCESS; } } // namespace ge namespace ops { class AddCustom : public OpDef { public: AddCustom(const char* name) : OpDef(name) { this-Input(x) .ParamType(REQUIRED) .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_INT32}) .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); this-Input(y) .ParamType(REQUIRED) .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_INT32}) .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); this-Output(z) .ParamType(REQUIRED) .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_INT32}) .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); // 根据用户的算子调用方式决定需不需要注册图模式调用方式下需要 this-SetInferShape(ge::InferShape); this-SetInferShapeRange(ge::InferShapeRange); this-SetInferDataType(ge::InferDataType); this-AICore() .SetTiling(optiling::TilingFunc); // 请替换为实际的昇腾AI处理器型号 this-AICore().AddConfig(ascendxxx); } }; OP_ADD(AddCustom); } // namespace opsdatatype推导以AddCustom算子为例InferDataType的实现如下所示。该样例中输出tensor的数据类型与输入tensor的数据类型相同所以直接将任意一个输入tensor的数据类型赋给输出tensor即可。namespace ge { static graphStatus InferDataType(gert::InferDataTypeContext* context) { const auto inputDataType context-GetInputDataType(0); context-SetOutputDataType(0, inputDataType); return ge::GRAPH_SUCCESS; } } // namespace ge如下示例则给出了更灵活的datatype推导样例当输入的数据类型为DT_INT4时其输出的数据类型为DT_INT32。ge::graphStatus InferDataTypeForFoo(gert::InferDataTypeContext* context) { if (context-GetInputDataType(0) DT_INT4) { context-SetOutputDataType(0, DT_INT32); } }shape推导简单的shape推导逻辑可以使用Follow接口来表达比如输出shape和输入shape相同的情况。示例如下输出“y1”Follow输入“x1”场景指定Follow模式为SHAPE此时“y1”的shape将会和“x1”保持一致。this-Input(x1) .ParamType(REQUIRED) .DataType({ge::DT_FLOAT, ge::DT_FLOAT}) .Format({ge::FORMAT_ND, ge::FORMAT_ND}); this-Input(x2) .ParamType(REQUIRED) .DataType({ge::DT_FLOAT, ge::DT_FLOAT}) .Format({ge::FORMAT_ND, ge::FORMAT_ND}); this-Output(y1) .ParamType(REQUIRED) .DataType({ge::DT_FLOAT, ge::DT_FLOAT}) .Format({ge::FORMAT_ND, ge::FORMAT_ND}) .Follow(x1, FollowType::SHAPE);无法在原型定义中通过Follow表达的情况需要开发者编写InferShape函数InferShape函数的原型是固定的如下示例接受一个InferShapeContext作为输入从此context上可以获取到输入、输出的shape指针等内容。输入shape为const类型因此InferShape时输入shape是只读、不允许修改的。InferShape成功后返回ge::GRAPH_SUCCESS其他返回值被认为推导失败。推导失败后执行过程结束退出。以ReShape算子为例InferShape的实现如下所示。根据第1个输入shape输入的值Reshape算子将第0个输入x输入的shape做变换并输出到其第0个输出y输出上。Reshape的InferShape实现为ge::graphStatus InferShapeForReshape(InferShapeContext *context) { const gert::Shape *x_shape context-GetInputShape(0); // 获取第0个输入的shape const gert::Tensor *shape_tensor context-GetInputTensor(1); // 获取第1个输入的tensor gert::Shape *output_shape context-GetOutputShape(0); if (x_shape nullptr || shape_tensor nullptr || output_shape nullptr) { // 防御式编程不应该出现的场景打印错误并返回失败 return ge::GRAPH_FAILED; } auto reshape_size static_castint32_t(shape_tensor-GetShapeSize()); if (reshape_size 1) { // 防御式编程不应该出现的场景打印错误并返回失败 return ge::GRAPH_FAILED; } // 根据原型信息Reshape的shape输入支持INT32与INT64两类根据不同的类型进入对应的模板函数中做真正的shape变换操作 if (shape_tensor-GetDataType() ge::DT_INT32) { int32_t *reshape_data shape_tensor-GetDataint32_t(); return ReshapeInferShapeImplint32_t(reshape_data, *x_shape, *output_shape, reshape_size); } else { int64_t *reshape_data shape_tensor-GetDataint64_t(); return ReshapeInferShapeImplint64_t(reshape_data, *x_shape, *output_shape, reshape_size); } }InferShapeContext public继承自ExtendedKernelContext因此ExtendedKernelContext中提供的方法如获取算子type、name、属性等接口均可以在InferShapeContext实例中调用。[!CAUTION]注意InferShape推导函数和Follow接口不能混用即不支持部分输出采用Infershape推导、部分输出采用Follow推导的情况。若用户同时使用了InferShape函数和Follow接口以用户的InferShape函数为准需要保证在InferShape函数中能够推导出所有的输出shape。为了效率考虑调用InferShape函数时框架不会为输出shape做初始化因此在InferShape函数中可以认为输出是未初始化的状态。如果在InferShape时希望通过Append方式操作输出shape需要先将输出shape的DimNum清零以防止出现未定义行为。InferShapeRange实现某些算子的输出Shape在计算完成后才能确定。比如unique算子其Shape的推导逻辑如下给定一维Tensor x找到其中不重复的元素返回去重后的Tensor y输出idx与输入x大小相同保存x每个元素在y中的索引。# tensor x is [1, 1, 2, 4, 4, 4, 7, 8, 8] x shape[9] y, idx unique(x) y [1, 2, 4, 7, 8] y shape[5] idx [0, 0, 1, 2, 2, 2, 3, 4, 4] idx shape[9]由此可知y的shape在编译时为[-1]unique执行后shape才确定。在入图场景执行时需要在执行前分配输出内存而内存的大小依赖于输出Shape和数据类型。对于此类算子由于输出Shape在执行后才能确定因此需要根据输出Shape的范围按照最大范围申请输出内存以确保有足够的空间供计算函数写入输出Tensor。这种场景下开发者需要自行实现InferShapeRange函数来推导输出Shape的范围。下面以unique算子为例子介绍InferShapeRange函数的实现方法。ge::graphStatus UniqueInferShapeRangeFunc(gert::InferShapeRangeContext *context) { // 取输入的shape range auto x_shape_range context-GetInputShapeRange(0U); OPS_CHECK_NULL_WITH_CONTEXT(context, x_shape_range); OPS_CHECK_NULL_WITH_CONTEXT(context, x_shape_range-GetMax()); OPS_CHECK_NULL_WITH_CONTEXT(context, x_shape_range-GetMin()); // 开始计算y输出的shape range auto y_shape_range context-GetOutputShapeRange(0U); OPS_CHECK_NULL_WITH_CONTEXT(context, y_shape_range); y_shape_range-GetMax()-SetDimNum(1); // 一维向量rank为1 y_shape_range-GetMin()-SetDimNum(1); auto x_max_shape x_shape_range-GetMax(); auto x_shape_dimnum x_max_shape-GetDim(0); // x为一维Tensor其shape为[n] x_shape_dimnum表示x输入的元素个数n if (x_shape_dimnum 1) { // 若x输入只有1个元素不存在去重y的shape轴最小最大均为1. 因此range为[1~1] y_shape_range-GetMax()-SetDim(0, 1); y_shape_range-GetMin()-SetDim(0, 1); } else { // 若x输入有0个元素或者大于1个元素去重后y的元素个数最小为x的min最大为x的max y_shape_range-GetMax()-SetDim(0, x_shape_dimnum); y_shape_range-GetMin()-SetDim(0, x_shape_range-GetMin()); } // 开始计算输出idx的shape range // 输出idx表示x元素在y中的索引其元素个数与x相等因此shape range与x一致 auto idx_shape_range context-GetOutputShapeRange(1U); OPS_CHECK_NULL_WITH_CONTEXT(context, idx_shape_range); *(idx_shape_range-GetMax()) *(x_shape_range-GetMax()); *(idx_shape_range-GetMin()) *(x_shape_range-GetMin()); return ge::GRAPH_SUCCESS; }InferShape时获取属性、输入在InferShape、Tiling时可以通过context实例获取算子IR属性值所谓IR属性是指在IR注册时定义的属性以TransData算子为例namespace ops { class TransData : public OpDef { public: explicit TransData(const char *name) : OpDef(name) { this-Input(src) ... this-Output(dst) ... this-Attr(src_format) .AttrType(REQUIRED) .String(); this-Attr(dst_format) .AttrType(REQUIRED) .String(); this-Attr(group) .AttrType(OPTIONAL) .Int(1); ... } }; OP_ADD(TransData); } // namespace ops其原型定义中声明了src_format、dst_format、group三个属性可以通过如下方式获取算子属性ge::graphStatus ExampleGetTransDataAttr(TilingContext *context) { // 获取所有属性 const RuntimeAttrs *attrs context-GetAttrs(); ASSERT_NOT_NULL(attrs); // 按照在原型定义中的顺序使用index获取属性index从0开始计数 const char *src_format attrs-GetAttrPointerchar(0); // 获取src_formatsrc_format是第一个属性因此index为0 const char *dst_format attrs-GetAttrPointerchar(1); // 获取dst_formatdst_format是第二个属性因此index为1 const int64_t group attrs-GetAttrPointerint64_t(2); // 获取groupgroup是第三个属性因此index为2 return ge::GRAPH_SUCCESS; }通过index而不是字符串name来索引输入输出对于带有OPTIONAL、DYNAMIC类型输入的算子可能出现实例化后单纯通过index无法索引到具体输入的问题以DynamicRNNV3算子为例namespace ops { class DynamicRNNV3 : public OpDef { public: explicit DynamicRNNV3(const char *name) : OpDef(name) { this-Input(x) .ParamType(REQUIRED) ... this-Input(w) .ParamType(REQUIRED) ... this-Input(b) .ParamType(REQUIRED) ... this-Input(seq_length) .ParamType(OPTIONAL) ... this-Input(init_h) .ParamType(OPTIONAL) ... this-Input(init_c) .ParamType(OPTIONAL) ... this-Input(wci) .ParamType(OPTIONAL) ... this-Input(wcf) .ParamType(OPTIONAL) ... this-Input(mask) .ParamType(OPTIONAL) ... this-Input(mask) .ParamType(OPTIONAL) ... this-Input(project) .ParamType(OPTIONAL) ... ... } }; OP_ADD(DynamicRNNV3); } // namespace ops由于DynamicRNNV3算子有连续的多个optional输入这导致init_h及其后面的输入的实例化后index都是不确定的对于这种类型的算子可以通过GetOptionalInputShape传入原型对应的index来获取对应的输入shape等数据以InferShape为例ge::graphStatus InferShapeForDynamicRNNV3(InferShapeContext *context) { // 对于前两个输入不受到optional或dynamic的影响可以按照常规方法获取输入shape auto x_shape context-GetInputShape(0); auto w_shape context-GetInputShape(1); if (x_shape nullptr || w_shape nullptr) { return ge::GRAPH_FAILED; } int64_t state_size 0; // 在原型定义上project是第11个输入(从0开始计数) constexpr int64_t kProjectInputIndex 11; // 受到前面optional输入影响的project实例化后输入的index是不确定的通过GetOptionalInputShape来获取对应的输入shape // GetOptionalInputShape的入参为原型上对应的index auto project_shape context-GetOptionalInputShape(kProjectInputIndex); if (project_shape ! nullptr) { if (project_shape-GetDimNum() 2) { return ge::GRAPH_FAILED; } state_size project_shape-GetDim(1); } // 更多的infershape逻辑... return ge::GRAPH_SUCCESS; }对于dynamic类型的输入实例化后的输入可能是一到多个对于此类输入获取方式为// ir_index此输入在原型定义中的index从0开始计数 // relative_index该输入实例化后的相对index从0开始计数例如某个DYNAMIC_INPUT实例化了3个要取第二个那么relative_index 1 auto shape context-GetDynamicInputShape(ir_index, relative_index);本节举例的获取optional、dynamic输入的方式在InferShape、Tiling函数中均可以调用。数据依赖一般来说具备输入shape后算子可以通过InferShape推导出输出shape。然而部分算子在InferShape时需要依赖某个输入的具体值才可以进行这类算子被称为“数据依赖算子”对应的输入被称为“数据依赖输入”。以Reshape算子为例其依据shape输入的描述对输入的shape做调整因此Reshape算子依赖shape输入的值。这类算子需要在原型定义时通过ValueDepend接口声明对应的输入为数据依赖输入。namespace ops { class Reshape : public OpDef { public: explicit Reshape(const char *name) : OpDef(name) { ... this-Input(shape) .ParamType(REQUIRED) ... .ValueDepend(REQUIRED) // 声明ReShape算子的shape输入为数据依赖输入 ... } }; OP_ADD(Reshape); } // namespace ops根据第1个输入shape输入的值Reshape算子将第0个输入x输入的shape做变换并输出到其第0个输出y输出上。Reshape的InferShape实现为// shape变换具体实现 templatetypename T ge::graphStatus ReshapeInferShapeImpl(const T *reshape_dims, const gert::Shape x_shape, gert::Shape output_shape, int32_t reshape_rank) { constexpr T UNKNOWN_DIM -1; // 将算子输出的维度数设置为reshape后的维度数reshape_rank output_shape.SetDimNum(reshape_rank); auto x_shape_size x_shape.GetShapeSize(); int64_t output_shapesize 1; size_t unknown_dim_idx std::numeric_limitssize_t::max(); for (int32_t i 0; i reshape_rank; i) { if (reshape_dims[i] ! UNKNOWN_DIM) { // reshape后某一轴的维度值不为-1 output_shape.SetDim(i, reshape_dims[i]); // 设置输出的维度值为reshape后的维度值 output_shapesize * reshape_dims[i]; // 计算当前输出元素数量 } else { output_shape.SetDim(i, 1); // reshape后某一轴的维度值为-1临时设置输出的维度值为1后续计算后看是否可以推导出确定值并记录未知维度的索引 unknown_dim_idx i; } } if (unknown_dim_idx std::numeric_limitssize_t::max() output_shapesize x_shape_size) { return ge::GRAPH_SUCCESS; // 不存在未知维度且输出shape size和输入x的shape size一致直接返回成功 } else if (unknown_dim_idx ! std::numeric_limitssize_t::max() x_shape_size % output_shapesize 0) { output_shape.SetDim(unknown_dim_idx, x_shape_size / output_shapesize); // 存在未知维度根据输入shape动态调整未知维度值保持总元素个数不变 return ge::GRAPH_SUCCESS; } return ge::GRAPH_FAILED; } ge::graphStatus InferShapeForReshape(InferShapeContext *context) { const gert::Shape *x_shape context-GetInputShape(0); // 获取第0个输入的shape const gert::Tensor *shape_tensor context-GetInputTensor(1); // 获取第1个输入的tensor gert::Shape *output_shape context-GetOutputShape(0); if (x_shape nullptr || shape_tensor nullptr || output_shape nullptr) { // 防御式编程不应该出现的场景打印错误并返回失败 return ge::GRAPH_FAILED; } auto reshape_size static_castint32_t(shape_tensor-GetShapeSize()); if (reshape_size 1) { // 防御式编程不应该出现的场景打印错误并返回失败 return ge::GRAPH_FAILED; } // 根据原型信息Reshape的shape输入支持INT32与INT64两类根据不同的类型进入对应的模板函数中做真正的shape变换操作 if (shape_tensor-GetDataType() ge::DT_INT32) { int32_t *reshape_data shape_tensor-GetDataint32_t(); return ReshapeInferShapeImplint32_t(reshape_data, *x_shape, *output_shape, reshape_size); } else { int64_t *reshape_data shape_tensor-GetDataint64_t(); return ReshapeInferShapeImplint64_t(reshape_data, *x_shape, *output_shape, reshape_size); } }[!CAUTION]注意只有声明过数据依赖的输入才可以在InferShape时调用GetInputTensor等获取tensor的接口获取其对应的tensor数据。若对一个未声明数据依赖的输入调用GetInputTensor等获取tensor的接口只能在tensor中获取到正确的shape、format、datatype信息无法获取到真实的tensor数据地址获取到的地址为nullptr。从tensor中获取tensor_data时(GetDataint32_t或GetDataint64_t)使用者需要保证获取的数据类型是正确的否则行为是未定义的。【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

ST-LINK_V2调试器核心功能与SWD接口实战指南

ST-LINK_V2调试器核心功能与SWD接口实战指南

1. ST-LINK_V2调试器核心功能解析ST-LINK_V2是STMicroelectronics官方推出的ARM Cortex-M系列微控制器调试编程工具,作为嵌入式开发者的"手术刀",它能精准完成芯片级调试、程序烧录和性能分析。与早期版本相比,V2版本在SWD协议支持…

2026/7/25 5:28:41 阅读更多 →
如何高效使用AutoHotkey实现谷歌浏览器自动化:专业实战指南

如何高效使用AutoHotkey实现谷歌浏览器自动化:专业实战指南

如何高效使用AutoHotkey实现谷歌浏览器自动化:专业实战指南 【免费下载链接】Chrome.ahk Automate Google Chrome using native AutoHotkey 项目地址: https://gitcode.com/gh_mirrors/ch/Chrome.ahk Chrome.ahk是一款强大的AutoHotkey谷歌浏览器自动化库&am…

2026/7/25 23:08:36 阅读更多 →
阿里二面挂了!被问“RAG效果不好怎么评估”,我答凭感觉,面试官:你搁这玄学炼丹呢?

阿里二面挂了!被问“RAG效果不好怎么评估”,我答凭感觉,面试官:你搁这玄学炼丹呢?

优化 RAG 系统时调参全凭感觉?本文带你走出“玄学评估”的泥潭。从核心的 RAG 三角评估模型(RAG Triad) 到 LLM-as-a-Judge 的成本陷阱,再到将 RAGAS 接入 CI/CD 流水线的降维打击。手把手教你搭建一套可量化、自动化的 AI 工程防…

2026/7/28 0:44:56 阅读更多 →

最新新闻

基于ESP32与视觉暂留原理的裸眼3D全息时钟DIY全攻略

基于ESP32与视觉暂留原理的裸眼3D全息时钟DIY全攻略

1. 项目概述:一个融合视觉与智能的桌面新宠最近在工作室的角落里,我给自己捣鼓了一个新玩意儿——一个能悬浮显示时间的WiFi时钟。它看起来就像科幻电影里的道具,时间数字仿佛凭空出现在一个透明的金字塔里,缓缓旋转,科…

2026/7/28 22:07:00 阅读更多 →
DataBase

DataBase

文章目录一、Oracle1.1 查询Oracle各项信息1.2 Oracle12c单机服务(启动/停止)1.3 Oracle 锁表与解锁1.4 Oracle常用函数二、Mysql2.1 Mysql基础2.1.1 数据存储结构2.1.2 索引2.1.3 SQL优化2.1.4 踩坑备忘2.2 查询Mysql5.7各项信息2.2.1 死锁日志分析2.2.…

2026/7/28 22:07:00 阅读更多 →
Unity DOTS BlobAsset:ECS架构下高性能只读数据共享方案详解

Unity DOTS BlobAsset:ECS架构下高性能只读数据共享方案详解

1. 项目概述:为什么我们需要 BlobAsset?如果你已经跟着 DOTS 系列一路走来,从 Entity 创建到 System 调度,再到 IComponentData 和 IJobEntity,你应该已经感受到了 ECS 架构在性能上的巨大潜力。数据紧密排列&#xff…

2026/7/28 22:07:00 阅读更多 →
如何在10分钟内为Honey Select 2安装终极汉化去码补丁:完整新手指南

如何在10分钟内为Honey Select 2安装终极汉化去码补丁:完整新手指南

如何在10分钟内为Honey Select 2安装终极汉化去码补丁:完整新手指南 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch HS2-HF Patch是专为Honey Selec…

2026/7/28 22:07:00 阅读更多 →
WordPress高转化技术栈:2024年性能优化实战指南

WordPress高转化技术栈:2024年性能优化实战指南

1. 项目概述:WordPress高转化技术栈的核心价值在数字营销领域,转化率提升1%可能意味着六位数的收入增长。作为从业12年的WordPress技术顾问,我见证了无数企业因技术栈选择不当而损失潜在客户。2024年的WordPress技术生态已发生质变&#xff0…

2026/7/28 22:07:00 阅读更多 →
排队免单模式的技术实现与商业价值

排队免单模式的技术实现与商业价值

1. 排队免单模式的商业本质解析这个模式最早出现在2022年华南地区的一家奶茶连锁品牌,当时单店单日最高创造了137万的流水记录。其核心逻辑在于将传统的"满减促销"转化为更具参与感的"概率游戏",通过精心设计的排队机制制造稀缺性和…

2026/7/28 22:05:59 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/28 12:04:22 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/28 8:29:16 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/28 5:03:42 阅读更多 →

月新闻