<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DashVector</title>
    <description>The latest articles on DEV Community by DashVector (@dashvector).</description>
    <link>https://dev.to/dashvector</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1523082%2F8505b9c1-aed6-4427-b8b1-acf93720fa8d.png</url>
      <title>DEV Community: DashVector</title>
      <link>https://dev.to/dashvector</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dashvector"/>
    <language>en</language>
    <item>
      <title>DashVector + ModelScope 玩转多模态检索</title>
      <dc:creator>DashVector</dc:creator>
      <pubDate>Fri, 24 May 2024 07:32:32 +0000</pubDate>
      <link>https://dev.to/dashvector/dashvector-modelscope-wan-zhuan-duo-mo-tai-jian-suo-5aad</link>
      <guid>https://dev.to/dashvector/dashvector-modelscope-wan-zhuan-duo-mo-tai-jian-suo-5aad</guid>
      <description>&lt;p&gt;本教程演示如何使用向量检索服务（DashVector），结合&lt;a href="https://modelscope.cn/home"&gt;ModelScope&lt;/a&gt;上的&lt;a href="https://modelscope.cn/models/damo/multi-modal_clip-vit-large-patch14_zh/summary"&gt;中文CLIP&lt;/a&gt;多模态检索模型，构建实时的"文本搜图片"的多模态检索能力。作为示例，我们采用&lt;a href="https://modelscope.cn/datasets/modelscope/muge/summary"&gt;多模态牧歌数据集&lt;/a&gt;作为图片语料库，用户通过输入文本来跨模态检索最相似的图片。&lt;/p&gt;

&lt;h2&gt;
  
  
  整体流程
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1r6q5pmjjhkj5zefd3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1r6q5pmjjhkj5zefd3g.png" alt="Image description" width="800" height="341"&gt;&lt;/a&gt;&lt;br&gt;
主要分为两个阶段：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;图片数据Embedding入库&lt;/strong&gt; 。将牧歌数据集通过中文CLIP模型Embedding接口转化为高维向量，然后写入DashVector向量检索服务。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;文本Query检索&lt;/strong&gt; 。使用对应的中文CLIP模型获取文本的Embedding向量，然后通过DashVector检索相似图片。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  前提准备
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. API-KEY 准备
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;开通向量检索服务：请参见&lt;a href="https://help.aliyun.com/document_detail/2568083.html?spm=a2c4g.2510236.0.i8"&gt;开通服务&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;创建向量检索服务API-KEY：请参见&lt;a href="https://help.aliyun.com/document_detail/2510230.html?spm=a2c4g.2510234.0.i9"&gt;API-KEY管理&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. 环境准备
&lt;/h3&gt;

&lt;p&gt;本教程使用的是ModelScope最新的CLIP &lt;a href="https://www.modelscope.cn/#/models/damo/multi-modal_clip-vit-huge-patch14_zh/summary"&gt;Huge模型(224分辨率)&lt;/a&gt;，该模型使用大规模中文数据进行训练（~2亿图文对），在中文图文检索和图像、文本的表征提取等场景表现优异。根据模型官网教程，我们提取出相关的环境依赖如下：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;需要提前安装 Python3.7 及以上版本，请确保相应的 python 版本&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 安装 dashvector 客户端
pip3 install dashvector

# 安装 modelscope
# require modelscope&amp;gt;=0.3.7，目前默认已经超过，您检查一下即可
# 按照更新镜像的方法处理或者下面的方法
pip3 install --upgrade modelscope -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html
# 需要单独安装decord
# pip3 install decord
# 另外，modelscope 的安装过程会出现其他的依赖，当前版本的依赖列举如下
# pip3 install torch torchvision opencv-python timm librosa fairseq transformers unicodedata2 zhconv rapidfuzz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 数据准备
&lt;/h3&gt;

&lt;p&gt;本教程使用&lt;a href="https://modelscope.cn/datasets/modelscope/muge/summary"&gt;多模态牧歌数据集&lt;/a&gt;的validation验证集作为入库的图片数据集，可以通过调用ModelScope的&lt;a href="https://modelscope.cn/docs/%E6%95%B0%E6%8D%AE%E9%9B%86%E4%BB%8B%E7%BB%8D"&gt;数据集&lt;/a&gt;接口获取。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from modelscope.msdatasets import MsDataset

dataset = MsDataset.load("muge", split="validation")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  具体步骤
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;本教程所涉及的 &lt;em&gt;your-xxx-api-key&lt;/em&gt; 以及 &lt;em&gt;your-xxx-cluster-endpoint&lt;/em&gt; ，均需要替换为您自己的API-KAY及CLUSTER_ENDPOINT后，代码才能正常运行。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 图片数据Embedding入库
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://modelscope.cn/datasets/modelscope/muge/summary"&gt;多模态牧歌数据集&lt;/a&gt;的 validation 验证集包含 30588 张多模态场景的图片数据信息，这里我们需要通过CLIP模型提取原始图片的Embedding向量入库，另外为了方便后续的图片展示，我们也将原始图片数据编码后一起入库。代码实例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import torch
from modelscope.utils.constant import Tasks
from modelscope.pipelines import pipeline
from modelscope.msdatasets import MsDataset
from dashvector import Client, Doc, DashVectorException, DashVectorCode
from PIL import Image
import base64
import io


def image2str(image):
    image_byte_arr = io.BytesIO()
    image.save(image_byte_arr, format='PNG')
    image_bytes = image_byte_arr.getvalue()
    return base64.b64encode(image_bytes).decode()


if __name__ == '__main__':
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 创建集合：指定集合名称和向量维度, CLIP huge 模型产生的向量统一为 1024 维
    rsp = client.create('muge_embedding', 1024)
    if not rsp:
        raise DashVectorException(rsp.code, reason=rsp.message)

    # 批量生成图片Embedding，并完成向量入库
    collection = client.get('muge_embedding')
    pipe = pipeline(task=Tasks.multi_modal_embedding,
                    model='damo/multi-modal_clip-vit-huge-patch14_zh', 
                    model_revision='v1.0.0')
    ds = MsDataset.load("muge", split="validation")

    BATCH_COUNT = 10
    TOTAL_DATA_NUM = len(ds)
    print(f"Start indexing muge validation data, total data size: {TOTAL_DATA_NUM}, batch size:{BATCH_COUNT}")
    idx = 0
    while idx &amp;lt; TOTAL_DATA_NUM:
        batch_range = range(idx, idx + BATCH_COUNT) if idx + BATCH_COUNT &amp;lt;= TOTAL_DATA_NUM else range(idx, TOTAL_DATA_NUM)
        images = [ds[i]['image'] for i in batch_range]
        # 中文 CLIP 模型生成图片 Embedding 向量
        image_embeddings = pipe.forward({'img': images})['img_embedding']
        image_vectors = image_embeddings.detach().cpu().numpy()
        collection.insert(
            [
                Doc(
                    id=str(img_id),
                    vector=img_vec,
                    fields={'png_img': image2str(img)}
                )
                for img_id, img_vec, img in zip(batch_range, image_vectors, images)
            ]
        )
        idx += BATCH_COUNT
    print("Finish indexing muge validation data")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;上述代码里模型默认在 cpu 环境下运行，在 gpu 环境下会视 gpu 性能得到不同程度的性能提升&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 文本Query检索
&lt;/h3&gt;

&lt;p&gt;完成上述图片数据向量化入库后，我们可以输入文本，通过同样的CLIP Embedding模型获取文本向量，再通过DashVector向量检索服务的检索接口，快速检索相似的图片了，代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import torch
from modelscope.utils.constant import Tasks
from modelscope.pipelines import pipeline
from modelscope.msdatasets import MsDataset
from dashvector import Client, Doc, DashVectorException
from PIL import Image
import base64
import io


def str2image(image_str):
    image_bytes = base64.b64decode(image_str)
    return Image.open(io.BytesIO(image_bytes))


def multi_modal_search(input_text):
    # 初始化 DashVector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('muge_embedding')

    # 获取文本 query 的 Embedding 向量
    pipe = pipeline(task=Tasks.multi_modal_embedding,
                    model='damo/multi-modal_clip-vit-huge-patch14_zh', model_revision='v1.0.0')
    text_embedding = pipe.forward({'text': input_text})['text_embedding']  # 2D Tensor, [文本数, 特征维度]
    text_vector = text_embedding.detach().cpu().numpy()[0]

    # DashVector 向量检索
    rsp = collection.query(text_vector, topk=3)
    image_list = list()
    for doc in rsp:
        image_str = doc.fields['png_img']
        image_list.append(str2image(image_str))
    return image_list


if __name__ == '__main__':
    text_query = "戴眼镜的狗"

    images = multi_modal_search(text_query)
    for img in images:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，输出结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frg2z4mmsxzd21g4pocvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frg2z4mmsxzd21g4pocvc.png" alt="Image description" width="771" height="793"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>DashVector + DashScope升级多模态检索</title>
      <dc:creator>DashVector</dc:creator>
      <pubDate>Fri, 24 May 2024 07:25:53 +0000</pubDate>
      <link>https://dev.to/dashvector/dashvector-dashscopesheng-ji-duo-mo-tai-jian-suo-4nl2</link>
      <guid>https://dev.to/dashvector/dashvector-dashscopesheng-ji-duo-mo-tai-jian-suo-4nl2</guid>
      <description>&lt;p&gt;本教程在前述教程（DashVector + ModelScope玩转多模态检索）的基础之上，基于DashScope上新推出的ONE-PEACE通用多模态表征模型结合向量检索服务DashVector来对多模态检索进行升级，接下来我们将展示更丰富的多模态检索能力。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://help.aliyun.com/document_detail/2510236.html?spm=a2c4g.2568028.0.i10"&gt;DashVector + ModelScope 玩转多模态检索&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dashscope.aliyun.com/"&gt;DashScope&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/one-peace-multimodal-embedding-quick-start"&gt;ONE-PEACE多模态模型&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;整体流程&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5n3a32ukf0p108p664r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5n3a32ukf0p108p664r.png" alt="Image description" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;主要分为两个阶段：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;多模态数据Embedding入库&lt;/strong&gt; 。通过ONE-PEACE模型服务&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/one-peace-multimodal-embedding-api-details"&gt;Embedding&lt;/a&gt;接口将多种模态的数据集数据转化为高维向量。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;多模态Query检索&lt;/strong&gt; 。基于ONE-PEACE模型提供的多模态Embedding能力，我们可以自由组合不同模态的输入，例如单文本、文本+音频、音频+图片等多模态输入，获取Embedding向量后通过DashVector跨模态检索相似结果。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;前提准备&lt;/strong&gt; 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. API-KEY 准备&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;开通灵积模型服务，并获得API-KEY：&lt;a href="//t2312925.md#"&gt;开通DashScope并创建API-KEY&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;开通DashVector向量检索服务，并获得API-KEY：&lt;a href="//t2364363.md#"&gt;API-KEY管理&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. 环境准备
&lt;/h3&gt;

&lt;p&gt;本教程使用的多模态推理模型服务是DashScope最新的&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/one-peace-multimodal-embedding-root"&gt;ONE-PEACE模型&lt;/a&gt;。ONE-PEACE是一个图文音三模态通用表征模型，在语义分割、音文检索、音频分类和视觉定位几个任务都达到了新SOTA表现，在视频分类、图像分类图文检索、以及多模态经典benchmark也都取得了比较领先的结果。模型相关的环境依赖如下：&lt;br&gt;
&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;需要提前安装Python3.7 及以上版本，请确保相应的python版本。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 安装 dashscope 和 dashvector sdk
pip3 install dashscope dashvector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  基本检索
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 数据准备
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;由于DashScope的ONE-PEACE模型服务当前只支持URL形式的图片、音频输入，因此需要将数据集提前上传到公共网络存储（例如 oss/s3），并获取对应图片、音频的url地址列表。&lt;/p&gt;

&lt;p&gt;当前示例场景使用&lt;a href="https://www.image-net.org/index.php"&gt;ImageNet-1k&lt;/a&gt;的validation数据集作为入库的图片数据集，将原始图片数据Embedding入库。检索时使用&lt;a href="https://github.com/karolpiczak/ESC-50"&gt;ESC-50&lt;/a&gt;数据集作为音频输入，文本和图片输入由用户自定义，用户也可对不同模态数据自由组合。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.image-net.org/download.php"&gt;Dataset for ImageNet-1k&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/karolpiczak/ESC-50"&gt;Dataset for ESC-50&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. 数据Embedding入库
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;本教程所涉及的 &lt;em&gt;your-xxx-api-key&lt;/em&gt; 以及 &lt;em&gt;your-xxx-cluster-endpoint&lt;/em&gt; ，均需要替换为您自己的API-KAY及CLUSTER_ENDPOINT后，代码才能正常运行。&lt;/p&gt;

&lt;p&gt;ImageNet-1k的validation数据集包含50000张标注好的图片数据，其中包含1000个类别，每个类别50张图片，这里我们基于ONE-PEACE模型提取原始图片的Embedding向量入库，另外为了方便后续的图片展示，我们也将原始图片的url一起入库。代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client, Doc, DashVectorException

dashscope.api_key = '{your-dashscope-api-key}'

# 由于 ONE-PEACE 模型服务当前只支持 url 形式的图片、音频输入，因此用户需要将数据集提前上传到
# 公共网络存储（例如 oss/s3），并获取对应图片、音频的 url 列表。
# 该文件每行存储数据集单张图片的公共 url，与当前python脚本位于同目录下
IMAGENET1K_URLS_FILE_PATH = "imagenet1k-urls.txt"


def index_image():
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 创建集合：指定集合名称和向量维度, ONE-PEACE 模型产生的向量统一为 1536 维
    rsp = client.create('imagenet1k_val_embedding', 1536)
    if not rsp:
        raise DashVectorException(rsp.code, reason=rsp.message)

    # 调用 dashscope ONE-PEACE 模型生成图片 Embedding，并插入 dashvector
    collection = client.get('imagenet1k_val_embedding')
    with open(IMAGENET1K_URLS_FILE_PATH, 'r') as file:
        for i, line in enumerate(file):
            url = line.strip('\n')
            input = [{'image': url}]
            result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                              input=input,
                                              auto_truncation=True)
            if result.status_code != 200:
                print(f"ONE-PEACE failed to generate embedding of {url}, result: {result}")
                continue
            embedding = result.output["embedding"]
            collection.insert(
                Doc(
                    id=str(i),
                    vector=embedding,
                    fields={'image_url': url}
                )
            )
            if (i + 1) % 100 == 0:
                print(f"---- Succeeded to insert {i + 1} image embeddings")


if __name__ == '__main__':
    index_image()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;上述代码需要访问DashScope的ONE-PEACE多模态Embedding模型，总体运行速度视用户开通该服务的qps有所不同。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;因图片大小影响ONE-PEACE模型获取Embedding的成功与否，上述代码运行后最终入库数据可能小于50000条。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. 模态检索
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3.1. 文本检索&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;对于单文本模态检索，可以通过ONE-PEACE模型获取文本Embedding向量，再通过DashVector向量检索服务的检索接口，快速检索相似的底库图片。这里文本query是猫 "cat"，代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client
from urllib.request import urlopen
from PIL import Image

dashscope.api_key = '{your-dashscope-api-key}'


def show_image(image_list):
    for img in image_list:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()


def text_search(input_text):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('imagenet1k_val_embedding')

    # 获取文本 query 的 Embedding 向量
    input = [{'text': input_text}]
    result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                      input=input,
                                      auto_truncation=True)
    if result.status_code != 200:
        raise Exception(f"ONE-PEACE failed to generate embedding of {input}, result: {result}")
    text_vector = result.output["embedding"]

    # DashVector 向量检索
    rsp = collection.query(text_vector, topk=3)
    image_list = list()
    for doc in rsp:
        img_url = doc.fields['image_url']
        img = Image.open(urlopen(img_url))
        image_list.append(img)
    return image_list


if __name__ == '__main__':
    """文本检索"""
    # 猫
    text_query = "cat"
    show_image(text_search(text_query))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5de6kulf7q3esype1fkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5de6kulf7q3esype1fkv.png" alt="Image description" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3.2. 音频检索
&lt;/h4&gt;

&lt;p&gt;单音频模态检索与文本检索类似，这里音频query取自ESC-50的"猫叫声"片段，代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client
from urllib.request import urlopen
from PIL import Image

dashscope.api_key = '{your-dashscope-api-key}'


def show_image(image_list):
    for img in image_list:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()


def audio_search(input_audio):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('imagenet1k_val_embedding')

    # 获取音频 query 的 Embedding 向量
    input = [{'audio': input_audio}]
    result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                      input=input,
                                      auto_truncation=True)
    if result.status_code != 200:
        raise Exception(f"ONE-PEACE failed to generate embedding of {input}, result: {result}")
    audio_vector = result.output["embedding"]

    # DashVector 向量检索
    rsp = collection.query(audio_vector, topk=3)
    image_list = list()
    for doc in rsp:
        img_url = doc.fields['image_url']
        img = Image.open(urlopen(img_url))
        image_list.append(img)
    return image_list


if __name__ == '__main__':
    """音频检索"""
    # 猫叫声
    audio_url = "http://proxima-internal.oss-cn-zhangjiakou.aliyuncs.com/audio-dataset/esc-50/1-47819-A-5.wav"
    show_image(audio_search(audio_url))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhx7k2957qwv75ib499bd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhx7k2957qwv75ib499bd.png" alt="Image description" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3.3. 文本+音频检索
&lt;/h4&gt;

&lt;p&gt;接下来，我们尝试"文本+音频"联合模态检索，同上，首先通过ONE-PEACE模型获取"文本+音频"输入的Embedding向量，再通过DashVector向量检索服务检索结果。这里的文本query选取的是草地"grass"，音频query依然选择的是ESC-50的"猫叫声"片段。代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client
from urllib.request import urlopen
from PIL import Image

dashscope.api_key = '{your-dashscope-api-key}'


def show_image(image_list):
    for img in image_list:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()


def text_audio_search(input_text, input_audio):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('imagenet1k_val_embedding')

    # 获取文本+音频 query 的 Embedding 向量
    input = [
        {'text': input_text},
        {'audio': input_audio},
    ]
    result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                      input=input,
                                      auto_truncation=True)
    if result.status_code != 200:
        raise Exception(f"ONE-PEACE failed to generate embedding of {input}, result: {result}")
    text_audio_vector = result.output["embedding"]

    # DashVector 向量检索
    rsp = collection.query(text_audio_vector, topk=3)
    image_list = list()
    for doc in rsp:
        img_url = doc.fields['image_url']
        img = Image.open(urlopen(img_url))
        image_list.append(img)
    return image_list


if __name__ == '__main__':
    """文本+音频检索"""
    # 草地
    text_query = "grass"
    # 猫叫声
    audio_url = "http://proxima-internal.oss-cn-zhangjiakou.aliyuncs.com/audio-dataset/esc-50/1-47819-A-5.wav"
    show_image(text_audio_search(text_query, audio_url))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcp29rx8ur5wiiqghsqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcp29rx8ur5wiiqghsqx.png" alt="Image description" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3.4. 图片+音频检索
&lt;/h4&gt;

&lt;p&gt;我们再尝试下"图片+音频"联合模态检索，与前述"文本+音频"检索类似，这里的图片选取的是草地图像（需先上传到公共网络存储并获取 url），音频query依然选择的是ESC-50的"猫叫声"片段。代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client
from urllib.request import urlopen
from PIL import Image

dashscope.api_key = '{your-dashscope-api-key}'


def show_image(image_list):
    for img in image_list:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()


def image_audio_search(input_image, input_audio):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('imagenet1k_val_embedding')

    # 获取图片+音频 query 的 Embedding 向量
    # 注意，这里音频 audio 模态输入的权重参数 factor 为 2（默认为1）
    # 目的是为了增大音频输入（猫叫声）对检索结果的影响
    input = [
        {'factor': 1, 'image': input_image},
        {'factor': 2, 'audio': input_audio},
    ]
    result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                      input=input,
                                      auto_truncation=True)
    if result.status_code != 200:
        raise Exception(f"ONE-PEACE failed to generate embedding of {input}, result: {result}")
    image_audio_vector = result.output["embedding"]

    # DashVector 向量检索
    rsp = collection.query(image_audio_vector, topk=3)
    image_list = list()
    for doc in rsp:
        img_url = doc.fields['image_url']
        img = Image.open(urlopen(img_url))
        image_list.append(img)
    return image_list


if __name__ == '__main__':
    """图片+音频检索"""
    # 草地
    image_url = "http://proxima-internal.oss-cn-zhangjiakou.aliyuncs.com/image-dataset/grass-field.jpeg"
    # 猫叫声
    audio_url = "http://proxima-internal.oss-cn-zhangjiakou.aliyuncs.com/audio-dataset/esc-50/1-47819-A-5.wav"
    show_image(image_audio_search(image_url, audio_url))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;输入示意图如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk6gsyasdjj09txdp2o9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk6gsyasdjj09txdp2o9.png" alt="Image description" width="336" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;运行代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40cef3zhqo4hhqwubut9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40cef3zhqo4hhqwubut9.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  进阶使用
&lt;/h2&gt;

&lt;p&gt;上述场景里作为检索底库数据的是单模态的图片数据，这里我们也可以将多种模态的数据同时通过ONE-PEACE模型获取Embedding向量，将Embedding向量作为检索库数据入库检索，观察检索效果。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 数据准备
&lt;/h3&gt;

&lt;p&gt;本示例场景使用&lt;a href="https://cocodataset.org/"&gt;微软COCO&lt;/a&gt;在Captioning场景下的validation数据集，将图片以及对应的图片描述caption文本两种模态数据一起Embedding入库。对于检索时输入的图片、音频与文本等多模态数据，用户可以自定义，也可以使用公共数据集的数据。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cocodataset.org/#download"&gt;Dataset for MSCOCO&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. 数据Embedding入库
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;本教程所涉及的 &lt;em&gt;your-xxx-api-key&lt;/em&gt; 以及 &lt;em&gt;your-xxx-cluster-endpoint&lt;/em&gt; ，均需要替换为您自己的API-KAY及CLUSTER_ENDPOINT后，代码才能正常运行。&lt;/p&gt;

&lt;p&gt;微软COCO的Captioning validation验证集包含5000张标注良好的图片及对应的说明文本，这里我们需要通过 DashScope的ONE-PEACE模型提取数据集的"图片+文本"的Embedding向量入库，另外为了方便后续的图片展示，我们也将原始图片url和对应caption文本一起入库。代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client, Doc, DashVectorException

dashscope.api_key = '{your-dashscope-api-key}'

# 由于 ONE-PEACE 模型服务当前只支持 url 形式的图片、音频输入，因此用户需要将数据集提前上传到
# 公共网络存储（例如 oss/s3），并获取对应图片、音频的 url 列表。
# 该文件每行存储数据集单张图片的公共 url 和对应的 caption 文本，以`;`分割
COCO_CAPTIONING_URLS_FILE_PATH = "cocoval5k-urls-captions.txt"


def index_image_text():
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 创建集合：指定集合名称和向量维度, ONE-PEACE 模型产生的向量统一为 1536 维
    rsp = client.create('coco_val_embedding', 1536)
    if not rsp:
        raise DashVectorException(rsp.code, reason=rsp.message)

    # 调用 dashscope ONE-PEACE 模型生成图片 Embedding，并插入 dashvector
    collection = client.get('coco_val_embedding')
    with open(COCO_CAPTIONING_URLS_FILE_PATH, 'r') as file:
        for i, line in enumerate(file):
            url, caption = line.strip('\n').split(";")
            input = [
                {'text': caption},
                {'image': url},
            ]
            result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                              input=input,
                                              auto_truncation=True)
            if result.status_code != 200:
                print(f"ONE-PEACE failed to generate embedding of {url}, result: {result}")
                continue
            embedding = result.output["embedding"]
            collection.insert(
                Doc(
                    id=str(i),
                    vector=embedding,
                    fields={'image_url': url, 'image_caption': caption}
                )
            )
            if (i + 1) % 20 == 0:
                print(f"---- Succeeded to insert {i + 1} image embeddings")


if __name__ == '__main__':
    index_image_text()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;上述代码需要访问DashScope的ONE-PEACE多模态Embedding模型，总体运行速度视用户开通该服务的qps有所不同。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 模态检索
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1. 文本检索
&lt;/h4&gt;

&lt;p&gt;首先我们尝试单文本模态检索。代码示例如下：&lt;br&gt;
Python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dashscope&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dashscope&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MultiModalEmbedding&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dashvector&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;urllib.request&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlopen&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="n"&gt;dashscope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{your-dashscope-api-key}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show_image_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_text_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;image_text_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
&lt;/span&gt;        &lt;span class="c1"&gt;# 建议在支持 jupyter notebook 的服务器上运行该代码
&lt;/span&gt;        &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;text_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# 初始化 dashvector client
&lt;/span&gt;    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{your-dashvector-api-key}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{your-dashvector-cluster-endpoint}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 获取上述入库的集合
&lt;/span&gt;    &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;coco_val_embedding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 获取文本 query 的 Embedding 向量
&lt;/span&gt;    &lt;span class="nb"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_text&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MultiModalEmbedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MultiModalEmbedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multimodal_embedding_one_peace_v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                      &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                      &lt;span class="n"&gt;auto_truncation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ONE-PEACE failed to generate embedding of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# DashVector 向量检索
&lt;/span&gt;    &lt;span class="n"&gt;rsp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;topk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;image_text_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rsp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;img_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;img_cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_caption&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;image_text_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_cap&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;image_text_list&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;文本检索&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# 狗
&lt;/span&gt;    &lt;span class="n"&gt;text_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dog&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="nf"&gt;show_image_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_query&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8m0504dmcz5gohfo941u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8m0504dmcz5gohfo941u.png" alt="Image description" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3.2. 音频检索
&lt;/h4&gt;

&lt;p&gt;我们再尝试单音频模态检索。我们使用ESC-50数据集的"狗叫声片段"作为音频输入，代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client
from urllib.request import urlopen
from PIL import Image

dashscope.api_key = '{your-dashscope-api-key}'


def show_image_text(image_text_list):
    for img, cap in image_text_list:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()
        print(cap)


def audio_search(input_audio):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('coco_val_embedding')

    # 获取音频 query 的 Embedding 向量
    input = [{'audio': input_audio}]
    result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                      input=input,
                                      auto_truncation=True)
    if result.status_code != 200:
        raise Exception(f"ONE-PEACE failed to generate embedding of {input}, result: {result}")
    audio_vector = result.output["embedding"]

    # DashVector 向量检索
    rsp = collection.query(audio_vector, topk=3)
    image_text_list = list()
    for doc in rsp:
        img_url = doc.fields['image_url']
        img_cap = doc.fields['image_caption']
        img = Image.open(urlopen(img_url))
        image_text_list.append((img, img_cap))
    return image_text_list


if __name__ == '__main__':
    """"音频检索"""
    # dog bark
    audio_url = "http://proxima-internal.oss-cn-zhangjiakou.aliyuncs.com/audio-dataset/esc-50/1-100032-A-0.wav"
    show_image_text(audio_search(audio_url))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpxvbdx7w3ipblfz4ct2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpxvbdx7w3ipblfz4ct2.png" alt="Image description" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3.3. 文本+音频检索
&lt;/h4&gt;

&lt;p&gt;进一步的，我们尝试使用"文本+音频"进行双模态检索。这里使用ESC-50数据集的"狗叫声片段"作为音频输入，另外使用"beach"作为文本输入，代码示例如下：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import dashscope
from dashscope import MultiModalEmbedding
from dashvector import Client
from urllib.request import urlopen
from PIL import Image

dashscope.api_key = '{your-dashscope-api-key}'


def show_image_text(image_text_list):
    for img, cap in image_text_list:
        # 注意：show() 函数在 Linux 服务器上可能需要安装必要的图像浏览器组件才生效
        # 建议在支持 jupyter notebook 的服务器上运行该代码
        img.show()
        print(cap)


def text_audio_search(input_text, input_audio):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取上述入库的集合
    collection = client.get('coco_val_embedding')

    # 获取文本+音频 query 的 Embedding 向量
    input = [
        {'text': input_text},
        {'audio': input_audio},
    ]
    result = MultiModalEmbedding.call(model=MultiModalEmbedding.Models.multimodal_embedding_one_peace_v1,
                                      input=input,
                                      auto_truncation=True)
    if result.status_code != 200:
        raise Exception(f"ONE-PEACE failed to generate embedding of {input}, result: {result}")
    text_audio_vector = result.output["embedding"]

    # DashVector 向量检索
    rsp = collection.query(text_audio_vector, topk=3)
    image_text_list = list()
    for doc in rsp:
        img_url = doc.fields['image_url']
        img_cap = doc.fields['image_caption']
        img = Image.open(urlopen(img_url))
        image_text_list.append((img, img_cap))
    return image_text_list


if __name__ == '__main__':
    """文本+音频检索"""
    text_query = "beach"
    # 狗叫声
    audio_url = "http://proxima-internal.oss-cn-zhangjiakou.aliyuncs.com/audio-dataset/esc-50/1-100032-A-0.wav"
    show_image_text(text_audio_search(text_query, audio_url))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;运行上述代码，检索结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlfqr1n7gc0jmf0o5sc4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlfqr1n7gc0jmf0o5sc4.png" alt="Image description" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;观察上述检索结果，发现后两张图的重点更多的是在展示 "beach" 文本输入对应的沙滩，而 "狗叫声片段"音频输入指示的狗的图片形象则不明显，其中第二张图需要放大后才可以看到图片中站立在水中的狗，第三张图中基本没有狗的形象。&lt;/p&gt;

&lt;p&gt;对于上述情况，我们可以通过&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/one-peace-multimodal-embedding-api-details"&gt;调整不同输入的权重&lt;/a&gt;来设置mbedding向量中哪种模态占更大的比重，从而在检索中突出重点。例如对于上述代码，我们可以给予"狗叫声片段"更大的权重，重点突出检索结果里狗的形象。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 其他代码一致

# 通过 `factor` 参数来调整不同模态输入的权重，默认为 1，这里设置 audio 为 2
input = [
    {'factor': 1, 'text': input_text},
    {'factor': 2, 'audio': input_audio},
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;替换 &lt;code&gt;input&lt;/code&gt;后，运行上述代码，结果如下：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtodlb36mnfdna2hjjhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtodlb36mnfdna2hjjhv.png" alt="Image description" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  写在最后
&lt;/h2&gt;

&lt;p&gt;本文结合&lt;a href="https://dashscope.aliyun.com"&gt;DashScope&lt;/a&gt;的ONE-PEACE模型的和&lt;a href="https://help.aliyun.com/document_detail/2510225.html?spm=a2c4g.2568028.0.i13"&gt;DashVector&lt;/a&gt;向量检索服务向大家展示了丰富多样的多模态检索示例，得益于ONE-PEACE模型优秀的多模态Embedding能力和DashVector强大的向量检索能力，我们能初步看到AI多模态检索令人惊喜的效果。&lt;/p&gt;

&lt;p&gt;本文的范例中，我们的向量检索服务，模型服务以及数据均可以公开获取，我们提供的示例也只是有限的展示了多模态检索的效果，非常欢迎大家来体验，自由发掘多模态检索的潜力。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>DashVector x 通义千问大模型：打造基于专属知识的问答服务</title>
      <dc:creator>DashVector</dc:creator>
      <pubDate>Fri, 24 May 2024 07:10:53 +0000</pubDate>
      <link>https://dev.to/dashvector/dashvector-x-tong-yi-qian-wen-da-mo-xing-da-zao-ji-yu-zhuan-shu-zhi-shi-de-wen-da-fu-wu-2f0</link>
      <guid>https://dev.to/dashvector/dashvector-x-tong-yi-qian-wen-da-mo-xing-da-zao-ji-yu-zhuan-shu-zhi-shi-de-wen-da-fu-wu-2f0</guid>
      <description>&lt;p&gt;===================================================&lt;/p&gt;

&lt;p&gt;本教程演示如何使用向量检索服务（DashVector），结合LLM大模型等能力，来打造基于垂直领域专属知识等问答服务。其中LLM大模型能力，以及文本向量生成等能力，这里基于&lt;a href="https://dashscope.aliyun.com/"&gt;灵积模型服务&lt;/a&gt;上的通义千问 API以及Embedding API来接入。&lt;/p&gt;

&lt;h2&gt;
  
  
  背景及实现思路 
&lt;/h2&gt;

&lt;p&gt;大语言模型（LLM）作为自然语言处理领域的核心技术，具有丰富的自然语言处理能力。但其训练语料库具有一定的局限性，一般由普适知识、常识性知识，如维基百科、新闻、小说，和各种领域的专业知识组成。导致 LLM 在处理特定领域的知识表示和应用时存在一定的局限性，特别对于垂直领域内，或者企业内部等私域专属知识。&lt;/p&gt;

&lt;p&gt;实现专属领域的知识问答的关键，在于如何让LLM能够理解并获取存在于其训练知识范围外的特定领域知识。同时可以通过特定Prompt构造，提示LLM在回答特定领域问题的时候，理解意图并根据注入的领域知识来做出回答。在通常情况下，用户的提问是完整的句子，而不像搜索引擎只输入几个关键字。这种情况下，直接使用关键字与企业知识库进行匹配的效果往往不太理想，同时长句本身还涉及分词、权重等处理。相比之下，倘若我们把提问的文本，和知识库的内容，都先转化为高质量向量，再通过向量检索将匹配过程转化为语义搜索，那么提取相关知识点就会变得简单而高效。&lt;/p&gt;

&lt;p&gt;接下来我们将基于&lt;a href="https://github.com/shijiebei2009/CEC-Corpus/"&gt;中文突发事件语料库&lt;/a&gt;（CEC Corpus）演示关于突发事件新闻报道的知识问答。&lt;/p&gt;

&lt;h2&gt;
  
  
  整体流程 
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8l2xtlek0drmh7tyvn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8l2xtlek0drmh7tyvn2.png" alt="Image description" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;主要分为三个阶段：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;本地知识库的向量化&lt;/strong&gt; 。通过文本向量模型将其转化为高质量低维度的向量数据，再写入DashVector向量检索服务。这里数据的向量化我们采用了&lt;a href="https://dashscope.aliyun.com/"&gt;灵积模型服务&lt;/a&gt;上的Embedding API实现。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;相关知识点的提取&lt;/strong&gt; 。将提问文本向量化后，通过 DashVector 提取相关知识点的原文。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;构造 Prompt 进行提问&lt;/strong&gt; 。将相关知识点作为"限定上下文+提问" 一起作为prompt询问通义千问。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  前提准备
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. API-KEY 和 Cluster准备
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;开通灵积模型服务，并获得 API-KEY。请参考：&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/activate-dashscope-and-create-an-api-key?spm=a2c4g.2510235.0.i10"&gt;开通DashScope并创建API-KEY&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;开通DashVector向量检索服务，并获得 API-KEY。请参考：DashVector &lt;a href="https://help.aliyun.com/document_detail/2510230.html?spm=a2c4g.2510235.0.i11"&gt;API-KEY管理&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;开通DashVector向量检索服务，并&lt;a href="https://help.aliyun.com/document_detail/2631966.html?spm=a2c4g.2510235.0.i12"&gt;创建Cluster&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;获取Cluster的Endpoint，Endpoint获取请查看 &lt;a href="https://help.aliyun.com/document_detail/2568084.html?spm=a2c4g.2510235.0.i13#3c0384e4e6asc"&gt;Cluster详情&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;灵积模型服务DashScope的API-KEY与DashVector的API-KEY是独立的，需要分开获取。&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 环境准备
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;需要提前安装 Python3.7 及以上版本，请确保相应的 python 版本。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install dashvector dashscope
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 数据准备
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/shijiebei2009/CEC-Corpus.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  搭建步骤 
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;本教程所涉及的 &lt;em&gt;your-xxx-api-key&lt;/em&gt; 以及 &lt;em&gt;your-xxx-cluster-endpoint&lt;/em&gt; ，均需要替换为您自己的API-KAY及CLUSTER_ENDPOINT后，代码才能正常运行。&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 本地知识库的向量化
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/shijiebei2009/CEC-Corpus"&gt;CEC-Corpus&lt;/a&gt;数据集包含 332 篇突发事件的新闻报道的语料和标注数据，这里我们只需要提取原始的新闻稿文本，并将其向量化后入库。文本向量化的教程可以参考&lt;a href="https://help.aliyun.com/document_detail/2510234.html?spm=a2c4g.2510235.0.i14"&gt;《基于向量检索服务与灵积实现语义搜索》&lt;/a&gt;。创建&lt;code&gt;embedding.py&lt;/code&gt;文件，并将如下示例代码复制到&lt;code&gt;embedding.py&lt;/code&gt;中：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dashscope&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dashscope&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TextEmbedding&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dashvector&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Doc&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prepare_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;batch_docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;batch_docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch_docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;batch_docs&lt;/span&gt;
                &lt;span class="n"&gt;batch_docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;batch_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;batch_docs&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_embeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rsp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TextEmbedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TextEmbedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_embedding_v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rsp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;embeddings&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;dashscope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{your-dashscope-api-key}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="c1"&gt;# 初始化 dashvector client
&lt;/span&gt;    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{your-dashvector-api-key}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{your-dashvector-cluster-endpoint}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 创建集合：指定集合名称和向量维度, text_embedding_v1 模型产生的向量统一为 1536 维
&lt;/span&gt;    &lt;span class="n"&gt;rsp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;news_embedings&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;rsp&lt;/span&gt;

    &lt;span class="c1"&gt;# 加载语料
&lt;/span&gt;    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;news_embedings&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;news&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;prepare_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CEC-Corpus/raw corpus/allSourceText&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;vectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_embeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# 写入 dashvector 构建索引
&lt;/span&gt;        &lt;span class="n"&gt;rsp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="nc"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;raw&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;news&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;rsp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;在示例中，我们将 Embedding 向量和新闻报道的文稿（作为raw字段）一起存入DashVector向量检索服务中，以便向量检索时召回原始文稿。&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 知识点的提取
&lt;/h3&gt;

&lt;p&gt;将 CEC-Corpus 数据集所有新闻报道写入DashVector服务后，就可以进行快速的向量检索。实现这个检索，我们同样将提问的问题进行文本向量化后，再在DashVector服务中检索最相关的知识点，也就是相关新闻报道。创建&lt;code&gt;search.py&lt;/code&gt;文件，并将如下示例代码复制到&lt;code&gt;search.py&lt;/code&gt;文件中。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from dashvector import Client

from embedding import generate_embeddings


def search_relevant_news(question):
    # 初始化 dashvector client
    client = Client(
      api_key='{your-dashvector-api-key}',
      endpoint='{your-dashvector-cluster-endpoint}'
    )

    # 获取刚刚存入的集合
    collection = client.get('news_embedings')
    assert collection

    # 向量检索：指定 topk = 1 
    rsp = collection.query(generate_embeddings(question), output_fields=['raw'],
                           topk=1)
    assert rsp
    return rsp.output[0].fields['raw']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 构造 Prompt 向LLM(通义千问)提问
&lt;/h3&gt;

&lt;p&gt;在通过提问搜索到相关的知识点后，我们就可以将 "提问 + 知识点" 按照特定的模板作为 prompt 向LLM发起提问了。在这里我们选用的LLM是通义千问，这是阿里巴巴自主研发的超大规模语言模型，能够在用户自然语言输入的基础上，通过自然语言理解和语义分析，理解用户意图。可以通过提供尽可能清晰详细的指令（prompt)，来获取更符合预期的结果。这些能力都可以通过&lt;a href="https://help.aliyun.com/document_detail/613695.html"&gt;通义千问API&lt;/a&gt;来获得。&lt;/p&gt;

&lt;p&gt;具体我们这里设计的提问模板格式为： &lt;em&gt;请基于我提供的内容回答问题。内容是{&lt;strong&gt;&lt;em&gt;}，我的问题是{&lt;/em&gt;&lt;/strong&gt;}&lt;/em&gt; ，当然您也可以自行设计合适的模板。创建&lt;code&gt;answer.py&lt;/code&gt;，并将如下示例代码复制到&lt;code&gt;answer.py&lt;/code&gt;中。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from dashscope import Generation


def answer_question(question, context):
    prompt = f'''请基于```

内的内容回答问题。"


    ```
    {context}
    ```


    我的问题是：{question}。
    '''

    rsp = Generation.call(model='qwen-turbo', prompt=prompt)
    return rsp.output.text


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  知识问答 
&lt;/h2&gt;

&lt;p&gt;做好这些准备工作以后，就可以对LLM做与具体知识点相关的提问了。比如在 CEC-Corpus 新闻数据集里，有如下一篇报道。因为整个新闻数据集已经在之前的步骤里，转换成向量入库了，我们现在就可以把这个新闻报道作为一个知识点，做出针对性提问：海南安定追尾事故，发生在哪里？原因是什么？人员伤亡情况如何？，并查看相应答案。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwz5rqkks8u83v1hxccg9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwz5rqkks8u83v1hxccg9.png" alt="Image description" width="800" height="483"&gt;&lt;/a&gt;&lt;br&gt;
创建&lt;code&gt;run.py&lt;/code&gt;文件，并将如下示例代码复制到&lt;code&gt;run.py&lt;/code&gt;文件中。&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import dashscope

from search import search_relevant_news
from answer import answer_question

if __name__ == '__main__':
    dashscope.api_key = '{your-dashscope-api-key}'

    question = '海南安定追尾事故，发生在哪里？原因是什么？人员伤亡情况如何？'
    context = search_relevant_news(question)
    answer = answer_question(question, context)

    print(f'question: {question}\n' f'answer: {answer}')


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwusf1ucih20rf2isuqyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwusf1ucih20rf2isuqyp.png" alt="Image description" width="800" height="188"&gt;&lt;/a&gt;&lt;br&gt;
可以看到，基于DashVector作为向量检索的底座，LLM大模型的知识范畴得到了针对性的扩展，并且能够对于专属的特定知识领域做出正确的回答。&lt;/p&gt;

&lt;h2&gt;
  
  
  写在最后 
&lt;/h2&gt;

&lt;p&gt;从本文的范例中，可以看到DashVector作为一个独立的向量检索服务，提供了开箱即用的强大向量检索服务能力，这些能力和各个AI模型结合，能够衍生多样的AI应用的可能。这里的范例中，LLM大模型问答，以及文本向量生成等能力，都是基于&lt;a href="https://dashscope.aliyun.com/"&gt;灵积模型服务&lt;/a&gt;上的通义千问API和Embedding API来接入的，在实际操作中，相关能力同样可以通过其他三方服务，或者开源模型社区，比如ModelScope上的&lt;a href="https://modelscope.cn/topic/dfefe5be778b49fba8c44646023b57ba/pub/summary"&gt;各种开源LLM模型&lt;/a&gt;来实现。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>基于向量检索服务与TextEmbedding实现语义搜索</title>
      <dc:creator>DashVector</dc:creator>
      <pubDate>Fri, 24 May 2024 07:01:07 +0000</pubDate>
      <link>https://dev.to/dashvector/ji-yu-xiang-liang-jian-suo-fu-wu-yu-textembeddingshi-xian-yu-yi-sou-suo-25lm</link>
      <guid>https://dev.to/dashvector/ji-yu-xiang-liang-jian-suo-fu-wu-yu-textembeddingshi-xian-yu-yi-sou-suo-25lm</guid>
      <description>&lt;p&gt;本教程演示如何使用向量检索服务（DashVector），结合&lt;a href="https://dashscope.aliyun.com/" rel="noopener noreferrer"&gt;灵积模型服务&lt;/a&gt;上的&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/api-details-15" rel="noopener noreferrer"&gt;Embedding API&lt;/a&gt;，来从0到1构建基于文本索引的构建+向量检索基础上的语义搜索能力。具体来说，我们将基于QQ 浏览器搜索标题语料库（&lt;a href="https://github.com/CLUEbenchmark/QBQTC" rel="noopener noreferrer"&gt;QBQTC&lt;/a&gt;：QQ Browser Query Title Corpus）进行实时的文本语义搜索，查询最相似的相关标题。&lt;/p&gt;

&lt;h2&gt;
  
  
  什么是 Embedding
&lt;/h2&gt;

&lt;p&gt;简单来说，Embedding是一个多维向量的表示数组，通常由一系列数字组成。Embedding可以用来表示任何数据，例如文本、音频、图片、视频等等，通过Embedding我们可以编码各种类型的非结构化数据，转化为具有语义信息的多维向量，并在这些向量上进行各种操作，例如相似度计算、聚类、分类和推荐等。&lt;/p&gt;

&lt;h2&gt;
  
  
  整体流程概述
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma41cld4lh25g361uhmf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fma41cld4lh25g361uhmf.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Embedding&lt;/strong&gt; ：通过DashScope提供的通用文本向量模型，对语料库中所有标题生成对应的embedding向量。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;构建索引服务和查询&lt;/strong&gt; ：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;通过DashVector向量检索服务对生成embedding向量构建索引。&lt;/li&gt;
&lt;li&gt;将查询文本embedding向量作为输入，通过DashVector搜索相似的标题。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  具体操作流程
&lt;/h2&gt;

&lt;h3&gt;
  
  
  前提条件
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;开通灵积模型服务，并获得 API-KEY：&lt;a href="https://help.aliyun.com/zh/dashscope/developer-reference/activate-dashscope-and-create-an-api-key?spm=a2c4g.2510234.0.i8" rel="noopener noreferrer"&gt;开通DashScope并创建API-KEY&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;开通DashVector向量检索服务，并获得 API-KEY&lt;a href="https://help.aliyun.com/document_detail/2510230.html?spm=a2c4g.2510234.0.i9" rel="noopener noreferrer"&gt;API-KEY管理&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1、环境安装
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;需要提前安装 Python3.7 及以上版本，请确保相应的 python 版本。&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

pip3 install dashvector dashscope


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  2、数据准备
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/CLUEbenchmark/QBQTC" rel="noopener noreferrer"&gt;QQ浏览器搜索相关性数据集&lt;/a&gt;（QBQTC, QQ Browser Query Title Corpus），是QQ浏览器搜索引擎目前针对大搜场景构建的一个融合了相关性、权威性、内容质量、 时效性等维度标注的学习排序（LTR）数据集，广泛应用在搜索引擎业务场景中。作为CLUE-beanchmark的一部分，QBQTC 数据集可以直接从github上下载（训练集路径为dataset/train.json）。&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone https://github.com/CLUEbenchmark/QBQTC.git
wc -l QBQTC/dataset/train.json


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;数据集中的训练集（train.json）其格式为 json：&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "id": 0, 
  "query": "小孩咳嗽感冒", 
  "title": "小孩感冒过后久咳嗽该吃什么药育儿问答宝宝树", 
  "label": "1"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;我们将从这个数据集中提取title，方便后续进行embedding并构建检索服务。&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import json

def prepare_data(path, size):
    with open(path, 'r', encoding='utf-8') as f:
        batch_docs = []
        for line in f:
            batch_docs.append(json.loads(line.strip()))
            if len(batch_docs) == size:
                yield batch_docs[:]
                batch_docs.clear()

        if batch_docs:
            yield batch_docs


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  3、通过 DashScope 生成 Embedding 向量
&lt;/h3&gt;

&lt;p&gt;DashScope灵积模型服务通过标准的API提供了多种模型服务。其中支持文本Embedding的模型中文名为通用文本向量，英文名为text-embedding-v1。我们可以方便的通过DashScope API调用来获得一段输入文本的embedding向量。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;需要使用您的api-key替换示例中的 &lt;em&gt;your-dashscope-api-key&lt;/em&gt; ，代码才能正常运行。&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import dashscope
from dashscope import TextEmbedding

dashscope.api_key='{your-dashscope-api-key}'


def generate_embeddings(text):
    rsp = TextEmbedding.call(model=TextEmbedding.Models.text_embedding_v1,
                             input=text)

    embeddings = [record['embedding'] for record in rsp.output['embeddings']]
    return embeddings if isinstance(text, list) else embeddings[0]


# 查看下embedding向量的维数，后面使用 DashVector 检索服务时会用到，目前是1536
print(len(generate_embeddings('hello')))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  4、通过 DashVector 构建检索：向量入库
&lt;/h3&gt;

&lt;p&gt;DashVector 向量检索服务上的数据以集合（Collection）为单位存储，写入向量之前，我们首先需要先创建一个集合来管理数据集。创建集合的时候，需要指定向量维度，这里的每一个输入文本经过DashScope上的text_embedding_v1模型产生的向量，维度统一均为1536。&lt;/p&gt;

&lt;p&gt;DashVector 除了提供向量检索服务外，还提供倒排过滤功能 和 scheme free 功能。所以我们为了演示方便，可以写入数据时，可以将title内容写入 DashVector 以便召回。写入数据还需要指定 id，我们可以直接使用 QBQTC 中id。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;需要使用您的api-key替换示例中的 &lt;em&gt;your-dashvector-api-key&lt;/em&gt; ，以及您的Cluster Endpoint替换示例中的 &lt;em&gt;your-dashvector-cluster-endpoint&lt;/em&gt; ，代码才能正常运行。&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

from dashvector import Client, Doc


# 初始化 DashVector client
client = Client(
  api_key='{your-dashvector-api-key}',
  endpoint='{your-dashvector-cluster-endpoint}'
)

# 指定集合名称和向量维度
rsp = client.create('sample', 1536)
assert rsp

collection = client.get('sample')
assert collection

batch_size = 10
for docs in list(prepare_data('QBQTC/dataset/train.json', batch_size)):
    # 批量 embedding
    embeddings = generate_embeddings([doc['title'] for doc in docs])

    # 批量写入数据
    rsp = collection.insert(
        [
            Doc(id=str(doc['id']), vector=embedding, fields={"title": doc['title']}) 
            for doc, embedding in zip(docs, embeddings)
        ]
    )
    assert rsp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  5、语义检索：向量查询
&lt;/h3&gt;

&lt;p&gt;在把QBQTC训练数据集里的title内容都写到DashVector服务上的集合里后，就可以进行快速的向量检索，实现"语义搜索"的能力。继续上面代码的例子，假如我们要搜索有多少和'应届生 招聘'相关的title内容，可以通过在DashVector上去查询'应届生 招聘'，即可迅速获取与该查询语义相近的内容，以及对应内容与输入之间的相似指数。&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# 基于向量检索的语义搜索
rsp = collection.query(generate_embeddings('应届生 招聘'), output_fields=['title'])

for doc in rsp.output:
    print(f"id: {doc.id}, title: {doc.fields['title']}, score: {doc.score}")


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

id: 0, title: 实习生招聘-应届生求职网, score: 2523.1582
id: 6848, title: 应届生求职网校园招聘yingjieshengcom中国领先的大学生求职网站, score: 3053.7095
id: 8935, title: 北京招聘求职-前程无忧, score: 5100.5684
id: 5575, title: 百度招聘实习生北京实习招聘, score: 5451.4155
id: 6500, title: 中公教育招聘信息网-招聘岗位-近期职位信息-中公教育网, score: 5656.128
id: 7491, title: 张家口招聘求职-前程无忧, score: 5834.459
id: 7520, title: 前程无忧网北京前程无忧网招聘, score: 5874.412
id: 3214, title: 乡镇卫生院招聘招聘乡镇卫生院招聘信息+-58同城, score: 6005.207
id: 6507, title: 赶集网招聘实习生北京实习招聘, score: 6424.9927
id: 5431, title: 实习内容安排百度文库, score: 6505.735


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
  </channel>
</rss>
