【技术解析 | 实践】Havenask-UDF定制

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
OpenSearch LLM智能问答版免费试用套餐,存储1GB首月+计算资源100CU
推荐全链路深度定制开发平台,高级版 1个月
简介: 本节分享 Havenask UDF定制相关的内容,共包含3个部分,分关于 Havenask 的 UDF 相关的介绍、自定义 UDF 的开发及配置方法的介绍,最后将进行 UDF 定制的实际操作演示。

一、UDF介绍

  • Havenask SQl 支持在查询语句中使用内置的 UDF,直译即用户自定义函数。同时也允许客户以插件的形式定制 UDF,客户可以自己开发并编译新的Havenask镜像以使用自定义的 UDF
  • Havenask 中已经有一些内置的 UDF,用户可以直接在查询中使用,例如用户可以通过 contain 函数判断某个字段的值是否在一个给定的集合内,或者使用MATCHINDEX QUERY 数查询倒排索引。
  • 还有可以计算向量查询分数或者文本匹配分的一些UDF,用户可以自行在查询中直接使用。


内置UDF列表

image.png


1、使用示例 A

例如 contain 函数,它的函数原型有以下6种,功能是判断第一个参数A中是否包含第二个参数 B中描述的内容。参数A可以是单值或多值的 int32int64string类型的字段,参数B为常量string表达式,表示的是一个给定的集合。集合的每个元素之间用竖线分割,返回值是布尔类型,表示参数 A的字段中是否包含参数 B所描述的集合。


原型

boolean contain(int32 a, const string b)

boolean contain(int64 a, const string b)

boolean contain(string a, const string b)

boolean contain(ARRAY a, const string b)

boolean contain(ARRAY a, const string b)

boolean contain(ARRAY a, const string b)


说明

判断单值或多值a中是否包含b中描述的内容

参数

参数a输入为单值多值的int32/int64/string 类型

参数b输入为常量string表达式,用 | 分隔,表示满足任意一项即可

返回值

boolean类型返回,表示参数a是否包含参数b中描述的集合


2、使用示例 B

例如用 contain 来检索 nid字段值在【1,2.3】这个集合中的所有记录。可以这样写 WHERE 子句:先将目标字段 nid作为 contain 的第一个参数,然后将给定的集合 1,2,3用以竖线分割的形式与成常量字符串作为 contain 函数的第二个参数。就能够通过 contain 检索到 nid 字段值在集合 1,2,3中的所有记录。

SELECT nid, price, brand, size FROM phone WHERE contain(nid, '1|2|3') ORDER BY nid LIMIT 100

USE_TIME: 0.059, ROW_COUNT: 3


------------------------------- TABLE INFO ---------------------------
nid   | price   | brand   | size  |
1   | 3599  | Huawei  | 5.9   |
2   | 4388  | Huawei  | 5.5   |
3     | 899     | Xiaomi  | 5     |


二、UDF开发及配置

1、UDF的开发

UDF的开发,可以参考udf_plugins路径下其他 UDF函数的实现,自定义 UDF 主要需要实现以下几个函数。

  • beginRequest函数,在 Query 开始时调用,可以初始化一些变量供后续使用。
  • evaluate 函数,在运行的过程中调用,将每条数据的相应字段送入该函数进行运算,并将 evaluate 的返回值作为最终结果。
  • creator 类的create Function 函数,用来创建 UDF 函数对象,可以做一些参数的检查,或者根据 UDF 的入参来创建不同的函数对象。开发完 UDF 的函数类和 creator 类之后需要在 HavenaskUdfFactory 中注册UDF。然后重新打包run time 镜像后才能使用新的自定义 UDF

image.png

image.png


2、UDF注册

开发完UDF的函数类和creator类之后,需要在HavenaskUdfFactory中注册这个UDF,然后重新打包runtime镜像后才能使用新的自定义UDF。

image.png


3、UDF配置

打镜像前还需要在 sql_function.json 配置中注册 UDF 原型,配置时可以参考每一项配置的说明。

  • 插件名称
  • 插件类型为UDF
  • is_determinisitic 表示输入相同时函数输出是否确定
  • 额外补充信息,例如UDF 中会使用到的 match data 的类型
  • 函数原型,其中也包括参数列表和返回值类型,可以注册多个函数原型
{
    "functions": [
        {
            "function_name": "cheap",                      // 1
            "function_type": "UDF",                         // 2
            "is_deterministic": 1,                          // 3
            "function_content_version": "json_default_0.1",
            "function_content": {
                "properties" : {},                          // 4
                "prototypes": [                             // 5
                    {
                        "params": [                         // 6
                            {
                                "is_multi": false,
                                "type": "double"
                            }
                        ],
                        "returns": [                        // 7
                            {
                                "is_multi": false,
                                "type": "boolean"
                            }
                        ]
                    }
                ]
            }
        }
    ]
}


三、实际操作演示

  • 首先进入ha3 dev 镜像,所有的开发都是在该镜像中完成,然后进入udf_plugins 目录。新建一个子目录cheap。我们将实现一个叫 cheap UDF,功能是判断一个字段的值是否小于2.000。此处已经写好了函数的相关实现,可以进去看一下具体的实现细节。
  • 首先来看一下头文件,头文件中包含了两个类,一个是 function 类,一个是 functionCreator 类。先来看 function 类,function 类接收一个 double 类型的字段作为输入然后在 query 开始时会调用 beginRequest函数,做一些初始化相关的操作。然后是 evaluate 函数,运行时会将每一条数据的相应字段,送入该函数进行运算,返回值作为最终的运算结果。这里 cheap 函数的作用是判断一个字段值是否小于 2000,所以返回值是一个布尔类型。

image.png


  • 再来看 functionCreator 类,这个类需要实现一个 createFunction 函数用来创建 function 类的对象。

image.png


再来看一下 CPP 文件,文件中是具体的函数实现。因为 cheap 函数实现比较简单,beginRequest没有需要做的事情,直接返回true 即可。evaluate 函数直接使用function 对象的 _pAttr 成员变量做一个判断,返回判断的结果即可。_pAttr 成员变量是在创建function 对象时通过构造函数传入。注意此处需要先调用getValue,才能从字段中获取到真正的值。functionCreator类的createFunction 函数的入参是查询语句中给 UDF 传入的参数,是一个 vector。我们可以在此处做一些参数的校验,先检查了入参不为空,然后又判断第一个字段不是多值类型的,防止创建函数出错。随后将 vector 的第一个元素作为 cheap 函数要判断的字段传入 UDF 对象中。然后需要在 Havenask UdfFactory.cpp中,注册该函数,此处仿照其他 UDF 的注册方法注册cheap 函数。

image.png


  • 接下来打开 udf_plugins 目录下的 BUILD 文件,将刚刚添加的cheap 目录下的所有 cpp 文件和头文件都加入 BUILD 文件的目标中。

image.png


  • 然后进入 sql目录下的misc 文件夹。编辑sql_function.json 配置文件,在最后加上我们的 cheap 的声明。开发都已完成。然后回到 Havenask 目录使用 build.sh 脚本编译代码。

image.png


  • 此处已经编译好。然后需要到容器的外边进入 docker目录下的runtime 子目录,将 bazel-bin 下刚刚编译好的hape_tar.tar 文件复制到子目录下。

image.png


  • 复制好之后需要使用docker build 的命令,打包一个新的镜像。例如镜像叫做ha3_runtime_udf。然后耐心等待镜像打包完成。打包完成后可以使用 docker 命令看到刚刚打好的镜像。可以看到这里已经有刚刚打好的ha3_runtime_udf镜像。

image.png


  • 然后更改 global.conf 配置,将所有的镜像都替换成ha3_runtime_udf

image.png


  • 这样下次使用hape 命令时就会使用刚刚打包好的镜像。然后使用hape 命令启动 havenask 服务,此处已经提前搭建好了一个 Havenask 服务,并且新建了一个商品表。先看看表里都有哪些数据。

image.png


  • 可以看到表中有商品id、商品 title 和商品price 字段,有的商品 price 价格大于 2.000 。可以通过在 WHERE 子句中使用定制好的 cheap 函数将价格大于2.000 的商品过滤掉。通过在原有查询中加上 WHERE 子句,将 price 字段传给 cheap 函数就可以得到过滤后的结果,可以看到所有价格大于2.000 的商品都已经被过滤。

image.png


四、结尾

具体HavenaskUDF定制的视频可以通过链接查看,欢迎各位开发者使用。

视频链接:https://developer.aliyun.com/live/253946?spm=a2c6h.12873587.live-index.30.3e4f7d23fFtlfg


关注我们:

Havenask 开源官网:https://havenask.net/

Havenask-Github 开源项目地址:https://github.com/alibaba/havenask

阿里云 OpenSearch 官网:https://www.aliyun.com/product/opensearch

钉钉扫码加入 Havenask 开源官方技术交流群:

1715594790746.png

目录
相关文章
|
7天前
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
38 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
4天前
|
编解码 人工智能 并行计算
基于 Megatron 的多模态大模型训练加速技术解析
Pai-Megatron-Patch 是一款由阿里云人工智能平台PAI 研发的围绕英伟达 Megatron 的大模型训练配套工具,旨在帮助开发者快速上手大模型,打通大模型相关的高效分布式训练、有监督指令微调、下游任务评估等大模型开发链路。本文以 Qwen2-VL 为例,从易用性和训练性能优化两个方面介绍基于 Megatron 构建的 Pai-Megatron-Patch 多模态大模型训练的关键技术
|
6天前
|
缓存 边缘计算 安全
阿里云CDN:全球加速网络的实践创新与价值解析
在数字化浪潮下,用户体验成为企业竞争力的核心。阿里云CDN凭借技术创新与全球化布局,提供高效稳定的加速解决方案。其三层优化体系(智能调度、缓存策略、安全防护)确保低延迟和高命中率,覆盖2800+全球节点,支持电商、教育、游戏等行业,帮助企业节省带宽成本,提升加载速度和安全性。未来,阿里云CDN将继续引领内容分发的行业标准。
49 7
|
7天前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
DeepSeek 实践应用解析:合力亿捷智能客服迈向 “真智能” 时代
DeepSeek作为人工智能领域的创新翘楚,凭借领先的技术实力,在智能客服领域掀起变革。通过全渠道智能辅助、精准对话管理、多语言交互、智能工单处理、个性化推荐、情绪分析及反馈监控等功能,大幅提升客户服务效率和质量,助力企业实现卓越升级,推动智能化服务发展。
43 1
|
9天前
|
机器学习/深度学习 人工智能 监控
鸿蒙赋能智慧物流:AI类目标签技术深度解析与实践
在数字化浪潮下,物流行业面临变革,传统模式的局限性凸显。AI技术为物流转型升级注入动力。本文聚焦HarmonyOS NEXT API 12及以上版本,探讨如何利用AI类目标签技术提升智慧物流效率、准确性和成本控制。通过高效数据处理、实时监控和动态调整,AI技术显著优于传统方式。鸿蒙系统的分布式软总线技术和隐私保护机制为智慧物流提供了坚实基础。从仓储管理到运输监控再到配送优化,AI类目标签技术助力物流全流程智能化,提高客户满意度并降低成本。开发者可借助深度学习框架和鸿蒙系统特性,开发创新应用,推动物流行业智能化升级。
|
4天前
|
缓存 算法 Oracle
深度干货 | 如何兼顾性能与可靠性?一文解析YashanDB主备高可用技术
数据库高可用(High Availability,HA)是指在系统遇到故障或异常情况时,能够自动快速地恢复并保持服务可用性的能力。如果数据库只有一个实例,该实例所在的服务器一旦发生故障,那就很难在短时间内恢复服务。长时间的服务中断会造成很大的损失,因此数据库高可用一般通过多实例副本冗余实现,如果一个实例发生故障,则可以将业务转移到另一个实例,快速恢复服务。
|
5天前
|
存储 前端开发 JavaScript
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。
|
7天前
|
存储 自然语言处理 监控
深度解析淘宝商品评论API接口:技术实现与应用实践
淘宝商品评论API接口是电商数据驱动的核心工具,帮助开发者高效获取用户评价、画像及市场趋势。其核心功能包括多维度信息采集、筛选排序、动态更新、OAuth 2.0认证和兼容多种请求方式。通过该接口,开发者可进行商品优化、竞品分析、舆情监控等。本文详细解析其技术原理、实战应用及挑战应对策略,助力开启数据驱动的电商运营新篇章。
|
9天前
|
人工智能 编解码 算法
视频云技术解析:春晚“子弹时间”背后的黑科技
视频云技术解析:春晚“子弹时间”背后的黑科技

推荐镜像

更多