创建 Embedding 函数

目标:利用阿里云百炼平台的 Embedding 函数,将文本和图片文件数据向量化,并实现以图搜图的场景。效果如下:

Step1:准备开发环境

  1. 安装 Docker:确保您的本地上安装了 Docker:https://www.docker.com/

  2. 拉取 Docker 镜像。在本地命令行终端(如 MacOS 的 ternmial)执行:

    [Local]# docker pull quay.io/pypa/manylinux2014_x86_64:2022-10-25-fbea779
  3. 启动 Docker 容器。该容器基于 manylinux2014_x86_64 镜像,并配置为使用 Python 3.10 环境

    [Local]# docker run -it --name cz_func --env PATH="/opt/python/cp310-cp310/bin:$PATH" quay.io/pypa/manylinux2014_x86_64:2022-10-25-fbea779 bash

4. 在 /root 目录下创建文件夹 embeddings

[root@docker root]# cd /root ; mkdir embeddings 
[root@docker embeddings]# cd embeddings
[root@docker embeddings]# touch gen_embeddings.py

5. cz_llm.py 中的程序代码如下:

import os
from cz.udf import annotate
from openai import OpenAI
import json

@annotate("*->string")
class get_embeddings(object):
    def evaluate(self, model_type, input_string, api_key, model_name, dim=None):

        if model_type == "text":
            # 初始化OpenAI客户端,使用用户提供的API密钥
            client = OpenAI(
                api_key=api_key,
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
            )

            input_data = input_string
            completion = client.embeddings.create(
                model=model_name,  # 使用用户提供的文本模型名称
                input=input_data,
                dimensions=int(dim),  # 指定向量维度
                encoding_format="float"
            )
            result_json = json.loads(completion.model_dump_json())
            embedding_vector = result_json['data'][0]['embedding']

        elif model_type == "multimodal":
            import dashscope
            image = input_string
            dashscope.api_key = api_key  # 使用用户提供的API密钥
            input = [{'image': image}]
            resp = dashscope.MultiModalEmbedding.call(
                model=model_name,  # 使用用户提供的多模态模型名称
                input=input
            )
            result_json = json.loads(json.dumps(resp.output, ensure_ascii=False, indent=4))
            embedding_vector = result_json['embeddings'][0]['embedding']
        else:
            return "Not Valid Model Type"

        if len(embedding_vector) >= 1:
            return str(embedding_vector)
        else:
            return "Not Valid"
# 添加命令行调用入口
if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description="Get Embeddings using OpenAI or DashScope")
    parser.add_argument('--model_type', required=True, help='Model type: text or multimodal')
    parser.add_argument('--input_string', required=True, help='The input string or image path')
    parser.add_argument('--api_key', required=True, help='Your API key')
    parser.add_argument('--model_name', required=True, help='Model name')
    parser.add_argument('--dim', default=1536, help='Vector dimensions (only for text models)')

    args = parser.parse_args()

    embedder = get_embeddings()
    result = embedder.evaluate(
        model_type=args.model_type,
        input_string=args.input_string,
        api_key=args.api_key,
        model_name=args.model_name,
        dim=args.dim
    )
    print(result)

Step2:下载第三方库

程序依赖第三方包:openai 需要进行下载(其余为Python 内置, osjson为 Python 内置库无需下载。 cz.udf 创建函数时系统会默认添加)

在开发环境中的命令行终端执行:

[root@docker embeddings]# pwd
/root/embeddings

[root@docker embeddings]# pip install openai -t .

此时目录结构类似于:

Step3:本地调试

将以3行做修改,因为当前环境还没有加载 cz.udf 库:

...
2 #from cz.udf import annotate   # 注释掉
...
6 #@annotate("*->string")  # 注释掉
...

其中 API_KEY 是阿里云百炼平台的 API-KEY ,需要您注册阿里云账号,登录后在这里获取:阿里云百炼

注释掉上面两行之后,保存退出编辑脚本。请注意把下面的 image_url 和 api_key 替换成真实的参数并执行:

[root@docker embeddings]# export PYTHONPATH="${_PWD}:${_PWD}/lib"
[root@docker embeddings]# python gen_embeddings.py \
    --model_type multimodal \
    --input_string ${image_url} \
    --api_key ${api_key} \
    --model_name multimodal-embedding-v1

Step4:打包上传

打包之前,请将上面注释掉的两行,解除注释。

...
2 from cz.udf import annotate   # 去掉注释
...
8 @annotate("*->string")  # 去掉注释

执行打包命令,保证当前目录为程序目录(本示例为 /root/cz_llm

[root@docker embeddings]# pwd
/root/embeddings
[root@docker embeddings]# zip -rq ../embeddings.zip ./
[root@docker embeddings]# ls ../

您会发现在 /root 目录下有一个 cz_llm.zip 文件,将这个文件拷贝到 Lakehouse USER VOLUME 对象中:

在 Docker 宿主机中执行:

[Local]# docker cp cz_func:/root/embeddings.zip ~/Downloads

现在 cz_llm.zip 在宿主机的用户的 Downloads 目录下

我们用 Lakehouse JDBC 客户端(请参考 Lakehouse JDBC 客户端),将文件 put 到 Lakehouse USER VOLUME 中:

PUT '/Users/derekmeng/Downloads/embeddings.zip' to USER VOLUME;

Step5:创建并使用函数:

本步骤依赖您提前创建好 API connection,创建过程请参考:API Connection

CREATE EXTERNAL FUNCTION public.fc_embeddings
AS 'gen_embeddings.get_embeddings'
USING ARCHIVE 'volume:user://~/embeddings.zip'
connection sg_fc_api_conn
WITH PROPERTIES (
'remote.udf.api' = 'python3.mc.v0'
)
COMMENT 'Examples:
For text: text <input_string> <api_key> <model_name> <dim>
For multimodal:multimodal <input_string> <api_key> <model_name>';
# Verify
select public.fc_embeddings('multimodal', 'http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/imagerecog/RecognizeFood/RecognizeFood5.jpg', '${api_key}', 'multimodal-embedding-v1');

执行效果:

接下来的步骤是实现以图搜图功能的核心步骤。该查询接收一个图片 URL,将其向量化,然后与数据表(food_images_data_vec)的所有图片向量进行比较。其中表 food_images_data_vec 的内容:

向量搜图的效果:

联系我们
预约咨询
微信咨询
电话咨询