本文面向首次体验 MaxCompute 文本向量检索的用户,通过 60 条中文示例文本演示如何使用 text-embedding-v4 生成向量、创建并重建向量索引,以及通过自然语言完成语义检索和类目标量过滤。
内容简介
使用
AI_EMBEDDING将文本转换为 256 维向量。创建 Append Delta Table 2.0 并存储 Vector 数据。
创建、重建并检查 HGraph 向量索引。
使用
VECTOR_SEARCH完成批量文本语义检索。在向量检索前使用标量条件缩小候选范围。
准备工作
开始前,请完成以下准备:
准备项 | 要求 |
阿里云账号和项目 | 已创建可用的 MaxCompute 项目 |
地域 | 目标项目所在地域支持 MaxCompute 模型计算服务和 |
模型计算服务 | 已在目标地域开通MaxCompute 模型计算服务。当前仅以下地域支持开通模型计算服务。地域和模型开放范围可能调整,执行前请以购买与使用MaxCompute 模型计算服务文档描述为准。
|
权限 | 当前账号可以创建表、写入数据、调用模型和管理向量索引 |
执行入口 |
|
本文统一使用 text-embedding-v4、DEFAULT_VERSION、256 维向量和 cosine 距离。文本库向量、Query 向量和索引距离类型必须保持一致。
模型计算费用:调用 text-embedding-v4 会产生 模型计算费用(Token费用),执行 SQL 和重建索引也会消耗计算资源。请关注实际用量和账单。
场景说明
本文构造一个包含 60 条数据的生活方式内容库:
类目 | 数量 | 内容示例 |
旅行 | 10 | 城市周末游、亲子自然体验、文化路线 |
数码 | 10 | 电脑续航、无线网络、手机存储和耳机使用 |
家居 | 10 | 收纳、清洁、照明和小空间布置 |
宠物 | 10 | 新手养猫、遛狗、饮水和日常护理 |
运动 | 10 | 跑步、骑行、游泳和居家训练 |
饮食 | 10 | 早餐、轻食、咖啡和家庭烹饪 |
每条数据包含唯一标识、标题、正文和类目。content 用于生成向量,title 和 category 用于展示和检查检索结果。
使用三条搜索文本:
Query ID | 搜索文本 |
Q001 | 周末想带孩子在杭州找一个能亲近自然又不太累的地方 |
Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? |
Q003 | 刚把小猫接回家,需要先买哪些用品 |
步骤一:配置 SQL 运行环境
登录MaxCompute控制台,在左上角选择地域。
在左侧导航栏,选择。
进入 SQL 查询页面。执行以下配置:
SET odps.sql.type.system.odps2=true; SET odps.sql.type.vector.enable=true; SELECT 1;odps2和 Vector 类型开关是使用 MaxCompute VECTOR数据类型的必要配置。本文后续 SQL 代码块均保留所需的会话配置,可以单独复制执行。如果使用 DataWorks,请在目标工作空间创建 ODPS SQL 节点,并选择相同的 MaxCompute 项目。
说明执行过程中若出现vector类型不兼容的问题,是由于目前部分项目使用SQL版本不一致,需要加Flag:
SET odps.task.major.version=vector_index_flighting;,后续版本一致后不需要再使用该Flag。
步骤二:创建并向量化文本库
创建文本向量表
VECTOR_SEARCH 要求输入表为 Delta Table。本文使用无主键 Append Delta Table,并通过 table.format.version=2 启用 Delta Table 2.0:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
CREATE TABLE IF NOT EXISTS text_search_corpus (
doc_id STRING,
title STRING,
content STRING,
category STRING,
text_embedding VECTOR(FLOAT, 256),
embedding_model STRING,
model_version STRING
)
TBLPROPERTIES ("table.format.version"="2");
写入示例数据并生成向量
以下 SQL 使用 VALUES 构造 60 条数据,并在写入时调用 AI_EMBEDDING 处理全部文本:
SET odps.namespace.schema=true;
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
SET odps.sql.ai.embedding.dimension=256;
INSERT OVERWRITE TABLE text_search_corpus
SELECT
doc_id,
title,
content,
category,
AI_EMBEDDING(
bigdata_public_modelset.default.`text-embedding-v4`,
DEFAULT_VERSION,
content
) AS text_embedding,
'text-embedding-v4' AS embedding_model,
'DEFAULT_VERSION' AS model_version
FROM (
VALUES
('T001', '西溪湿地亲子观鸟', '西溪湿地水网密布,步道平缓,春秋两季适合家长带孩子观察水鸟和湿地植物,半天即可完成主要路线。', '旅行'),
('T002', '西湖清晨慢行路线', '从断桥沿北山街步行到曲院风荷,清晨游客较少,路线平坦,适合希望轻松欣赏湖景的人群。', '旅行'),
('T003', '京杭运河夜游体验', '傍晚从武林门码头乘船游览运河,可以看到桥梁、历史街区和两岸灯光,适合安排在城市行程的最后一晚。', '旅行'),
('T004', '良渚文化一日参观', '上午参观良渚博物院了解文明起源,下午前往遗址公园体验考古场景,建议提前预约并准备防晒用品。', '旅行'),
('T005', '莫干山入门徒步', '选择竹林和村落相连的短线,累计爬升较小,普通运动鞋即可完成,适合第一次尝试山野徒步的游客。', '旅行'),
('T006', '千岛湖湖畔骑行', '沿湖绿道视野开阔,可根据体力选择二十至四十公里路线,途中设置多个补给点和观景平台。', '旅行'),
('T007', '上海老建筑漫步', '从武康路出发串联湖南路和复兴西路,沿途可观察不同年代的住宅建筑,也方便随时进入咖啡馆休息。', '旅行'),
('T008', '苏州园林错峰游览', '上午开园后先参观热门园林,再步行前往邻近的小型园林,可以减少排队并感受不同空间尺度。', '旅行'),
('T009', '宁波海边周末计划', '第一天游览渔港和海边步道,第二天安排海鲜市场和古村,行程节奏舒缓,适合两天短途出行。', '旅行'),
('T010', '南京博物馆路线', '将南京博物院、城墙遗址和历史街区安排在同一天,公共交通连接方便,雨天也能完成大部分行程。', '旅行'),
('D011', '延长笔记本续航时间', '外出办公时可降低屏幕亮度,关闭不用的蓝牙和后台同步程序,并启用系统节能模式,以减少电池消耗。', '数码'),
('D012', '改善家庭无线网络', '路由器应放在住宅中央且避免被金属柜遮挡,大户型可以增加网状网络节点,减少远端房间信号衰减。', '数码'),
('D013', '释放手机存储空间', '先检查视频、聊天附件和重复照片占用,再清理长期不用的应用,并将重要文件备份到可靠的云端或电脑。', '数码'),
('D014', '蓝牙耳机连接异常', '耳机无法配对时,可删除旧的配对记录,重启手机与耳机,再确认耳机已进入可发现状态。', '数码'),
('D015', '手机照片安全备份', '开启自动备份后仍应定期检查同步状态,重要照片可以同时保存到电脑或另一处存储,避免只保留单一副本。', '数码'),
('D016', '长时间看屏幕更舒适', '根据环境光调整显示器亮度,适当放大文字,并让屏幕上沿接近视线高度,每隔一段时间眺望远处。', '数码'),
('D017', '路由器摆放原则', '不要把路由器放在地面、墙角或大型电器旁,尽量保持周围开阔,并让常用房间与设备之间少隔承重墙。', '数码'),
('D018', '手机快充时发热', '充电时运行大型游戏会增加发热,建议停止高负载应用,使用匹配的充电器,并保持设备周围通风。', '数码'),
('D019', '机械键盘日常清洁', '断电后先用气吹清理键帽缝隙,再用微湿软布擦拭表面,避免液体直接进入轴体和电路板。', '数码'),
('D020', '视频会议减少环境噪声', '优先使用带麦克风的耳机,关闭房间内持续噪声源,并在会议软件中开启回声消除和降噪功能。', '数码'),
('H021', '小玄关收纳方法', '利用墙面挂钩、窄鞋柜和分层托盘分别收纳外套、鞋子与钥匙,让进出门常用物品保持固定位置。', '家居'),
('H022', '厨房油污快速清洁', '烹饪结束后趁灶台仍有余温及时擦拭,顽固油污可先用温和清洁剂湿敷,再用软布处理。', '家居'),
('H023', '卧室照明分层设计', '除了主灯,可在床头增加低亮度阅读灯,并使用暖色间接光,满足阅读、起夜和放松等不同需求。', '家居'),
('H024', '潮湿卫生间防霉', '洗浴后及时开启排风并刮走墙面水分,定期清洁瓷砖缝隙,减少长期潮湿造成的霉斑。', '家居'),
('H025', '书桌线缆整理', '将插线板固定在桌下,用理线夹区分电源线和数据线,并为经常插拔的线材保留适当余量。', '家居'),
('H026', '小户型功能分区', '可通过地毯、矮柜和灯光划分工作与休息区域,避免使用厚重隔断,让采光和通行保持连续。', '家居'),
('H027', '床垫日常维护', '定期更换床单并使用吸尘器清理表面,根据产品说明旋转床垫方向,保持卧室通风和干燥。', '家居'),
('H028', '冰箱分类收纳', '将即食食品与生鲜分层摆放,用透明盒标记开封日期,并把临期食材放在容易看到的位置。', '家居'),
('H029', '阳台耐养植物', '光照充足的阳台可选择迷迭香和薄荷,光线较弱时可考虑绿萝,浇水前先检查土壤湿度。', '家居'),
('H030', '换季衣物整理', '清洗并完全晾干后再收纳衣物,按家庭成员和使用频率分类,容易受潮的空间应增加防潮措施。', '家居'),
('P031', '新猫到家用品清单', '接猫前应准备猫砂盆、猫砂、食盆、饮水碗、适龄主粮、猫抓板和安全的躲藏空间,先让它安静适应。', '宠物'),
('P032', '鼓励猫咪多喝水', '可以把水碗远离食盆和猫砂盆,分散放置多个饮水点,并保持每天换水,部分猫更喜欢流动水。', '宠物'),
('P033', '建立稳定遛狗习惯', '每天尽量在相近时间外出,根据犬只年龄和体力调整时长,并留出闻嗅环境的时间,而不只是快速行走。', '宠物'),
('P034', '宠物换粮过渡方法', '新旧粮应在数天内逐步调整比例,同时观察食欲和排便情况,突然完全更换容易引起肠胃不适。', '宠物'),
('P035', '减少猫抓家具', '在猫经常停留和抓挠的位置放置稳定的猫抓板,通过玩具和奖励引导使用,不要只靠驱赶。', '宠物'),
('P036', '宠物口腔日常护理', '从短时间接触牙齿和牙龈开始训练,逐步使用宠物专用牙刷与牙膏,并定期检查口腔异味和牙结石。', '宠物'),
('P037', '让宠物适应航空箱', '平时将航空箱放在家中并保持开门,在内部放置熟悉的垫子和零食,让宠物把它视为安全空间。', '宠物'),
('P038', '减少家中宠物毛发', '定期梳毛能在脱落前收集浮毛,布艺表面可使用吸尘器和粘毛工具,同时清洁空调与净化器滤网。', '宠物'),
('P039', '老年犬生活调整', '提供防滑地垫和容易进出的休息区,缩短单次运动时间但保持规律,并关注体重、食欲和行动变化。', '宠物'),
('P040', '夏季宠物防暑', '避免在正午高温时段外出,确保随时有清洁饮水,不要把宠物单独留在封闭车辆或暴晒空间。', '宠物'),
('S041', '零基础开始跑步', '先采用快走与慢跑交替的方式,每周安排两到三次,逐步增加连续跑步时间,不必一开始追求速度。', '运动'),
('S042', '运动前动态热身', '可通过摆腿、弓步和肩部环绕逐渐提高心率,让关节进入活动状态,避免直接进行高强度动作。', '运动'),
('S043', '城市骑行安全准备', '出发前检查轮胎和刹车,正确佩戴头盔,夜间使用前后灯,并尽量选择自行车道或车流较少的路线。', '运动'),
('S044', '游泳换气入门练习', '先在浅水区练习水下缓慢呼气和侧头吸气,再配合打腿和划臂,减少因为憋气造成的紧张。', '运动'),
('S045', '居家力量训练安排', '深蹲、俯卧撑和臀桥可以覆盖主要肌群,每周训练两到三次,动作稳定后再增加次数或阻力。', '运动'),
('S046', '运动后放松原则', '结束后先用低强度活动让心率逐渐下降,再进行温和拉伸,不应通过剧烈按压追求明显疼痛感。', '运动'),
('S047', '短途徒步装备清单', '准备合脚的鞋、防晒用品、饮水、少量能量食品和轻便雨具,并提前下载路线或离线地图。', '运动'),
('S048', '办公室肩颈活动', '每工作一段时间起身活动,通过肩胛后收、颈部轻柔转动和胸椎伸展缓解长时间固定姿势。', '运动'),
('S049', '跳绳新手训练', '先掌握低高度双脚跳和稳定节奏,选择有缓冲的地面,以短组多次方式练习,逐步增加总时间。', '运动'),
('S050', '高强度训练后恢复', '训练后补充水分和正常饮食,保证睡眠,并在第二天安排低强度活动,持续疼痛时应停止加量。', '运动'),
('F051', '十分钟均衡早餐', '可以组合全麦面包、鸡蛋、无糖酸奶和水果,提前准备部分食材,在时间紧张时也能兼顾蛋白质和碳水。', '饮食'),
('F052', '工作日晚餐快速准备', '周末提前清洗分装蔬菜和肉类,工作日采用一锅煮或快炒方式,减少临时决定菜单和处理食材的时间。', '饮食'),
('F053', '家庭冷萃咖啡做法', '将中度研磨咖啡粉与冷水混合后冷藏浸泡,再过滤饮用,调整粉水比例可以改变浓度和口感。', '饮食'),
('F054', '让蔬菜口感更丰富', '根据蔬菜含水量选择快炒、烤制或焯水,搭配坚果、香草和少量调味汁,可以增加不同层次。', '饮食'),
('F055', '上班便当准备思路', '主食、蛋白质和两种蔬菜分别制作后组合,装盒前充分放凉,并根据保存时间选择冷藏或冷冻。', '饮食'),
('F056', '空气炸锅使用技巧', '食材不要堆得过满,中途翻面有助于受热均匀,含油较少的食材可在表面薄薄刷油改善口感。', '饮食'),
('F057', '逐步增加全谷物', '可以先用一部分糙米、燕麦或杂粮替换精制主食,逐渐调整比例,让口感和消化过程更容易适应。', '饮食'),
('F058', '减少含糖饮料摄入', '从降低饮用频率开始,用无糖茶、气泡水或加水果片的水替代,并避免在家中大量囤放甜饮料。', '饮食'),
('F059', '冷冻食材分类管理', '按一次使用量分装并标记名称和日期,新的食材放在后方,优先使用较早冷冻的库存。', '饮食'),
('F060', '厨房刀具基础使用', '保持砧板稳定,手指弯曲收拢并让刀面贴近指关节移动,切配完成后及时清洗和擦干刀具。', '饮食')
) sample_data(doc_id, title, content, category)
WHERE content IS NOT NULL
AND TRIM(content) <> '';
执行以下 SQL,检查数据和向量是否完整:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
SELECT
COUNT(*) AS total_count,
COUNT(DISTINCT doc_id) AS unique_doc_count,
SUM(CASE WHEN text_embedding IS NOT NULL THEN 1 ELSE 0 END) AS embedding_count
FROM text_search_corpus;
-- 返回结果:
+-------------+------------------+-----------------+
| total_count | unique_doc_count | embedding_count |
+-------------+------------------+-----------------+
| 60 | 60 | 60 |
+-------------+------------------+-----------------+若 embedding_count 小于 60,请停止后续步骤,并检查模型计算服务、地域、权限和输入文本。AI_EMBEDDING 对 NULL 或空字符串返回 NULL。
步骤三:创建并重建向量索引
VECTOR INDEX 当前仅支持在 Delta Table 上创建。为 text_embedding 创建 HGraph 索引:
-- 创建 VECTOR INDEX 前请执行以下命令,设置允许表结构变更(Schema Evolution)
SETPROJECT odps.schema.evolution.enable=true;
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
CREATE VECTOR INDEX idx_text_search_corpus_embedding
ON text_search_corpus (text_embedding)
IDXPROPERTIES (
'algorithm' = 'hgraph',
'distance_type' = 'cosine',
'build_params' = '{"max_degree": 16, "ef_construction": 128}'
);
CREATE VECTOR INDEX 用于定义索引。建议先参考索引参数配置说明,以获取最佳的资源使用配置和召回率。由于示例数据已写入表中,继续执行全量重建:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
ALTER TABLE text_search_corpus
REBUILD INDEX idx_text_search_corpus_embedding;重建完成后,查看索引信息:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
DESC INDEX idx_text_search_corpus_embedding
ON text_search_corpus;
-- 返回结果:
+------------------------------------------------------------------------------------+
| Index Detail |
+------------------------------------------------------------------------------------+
| name: idx_text_search_corpus_embedding |
| id: e9e97a6****************e8e8bbbdc |
| index_type: VECTOR |
| index_columns: text_embedding |
| status: ACTIVE |
| coverage_percentage: 100% |
| storage_size_bytes: 63353 |
| properties: build_params={"max_degree": 16, "ef_construction": 128}, distance_type=cosine, algorithm=hgraph |
+------------------------------------------------------------------------------------+预期结果:
status为ACTIVE。coverage_percentage为100%。properties中包含algorithm=hgraph和distance_type=cosine。
VECTOR INDEX明确列出的索引算法为 hgraph。max_degree 控制节点最大连接数,ef_construction 控制构建阶段候选列表大小。如果目标环境列出其他算法,请以该环境对应版本的文档为准。重建索引会消耗计算资源。本教程的数据量仅用于验证操作流程,不能用于评估索引性能。
步骤四:创建搜索文本并生成向量
创建 Query 表并生成三条查询向量。Query 与文本库必须使用相同的模型、版本和向量维度:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
CREATE TABLE IF NOT EXISTS text_search_query (
query_id STRING,
query_text STRING,
query_embedding VECTOR(FLOAT, 256),
embedding_model STRING,
model_version STRING
)
TBLPROPERTIES ("table.format.version"="2");SET odps.namespace.schema=true;
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
SET odps.sql.ai.embedding.dimension=256;
INSERT OVERWRITE TABLE text_search_query
SELECT
query_id,
query_text,
AI_EMBEDDING(
bigdata_public_modelset.default.`text-embedding-v4`,
DEFAULT_VERSION,
query_text
) AS query_embedding,
'text-embedding-v4' AS embedding_model,
'DEFAULT_VERSION' AS model_version
FROM (
VALUES
('Q001', '周末想带孩子在杭州找一个能亲近自然又不太累的地方'),
('Q002', '准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子?'),
('Q003', '刚把小猫接回家,需要先买哪些用品')
) query_data(query_id, query_text);
执行检索前检查 Query 向量:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
SELECT
query_id,
query_text,
CASE
WHEN query_embedding IS NOT NULL THEN 'READY'
ELSE 'FAILED'
END AS embedding_status
FROM text_search_query
ORDER BY query_id;
-- 返回结果:
+----------+----------------------------------------------------------------+------------------+
| query_id | query_text | embedding_status |
+----------+----------------------------------------------------------------+------------------+
| Q001 | 周末想带孩子在杭州找一个能亲近自然又不太累的地方 | READY |
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | READY |
| Q003 | 刚把小猫接回家,需要先买哪些用品 | READY |
+----------+----------------------------------------------------------------+------------------+预期结果: 三条记录的 embedding_status 均为 READY。如果存在 FAILED,请检查 Query 是否为空,并确认使用的模型、版本和向量维度与文本库一致。
步骤五:执行文本语义检索
执行以下 SQL,为每条 Query 返回 Top 3。示例为 VECTOR_SEARCH 的两个输入显式指定 base 和 query 别名,并通过别名限定向量列和返回字段。
base和query是本示例显式指定的输入别名。当两个输入包含同名列时,请使用base.<column>和query.<column>明确字段来源。若省略别名,第一个输入的默认别名为_base,第二个输入的默认别名为_query。Cosine是距离类型枚举值,不能加引号。请写成Cosine,不能写成'Cosine'。
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
SET odps.task.major.version=vector_index_flighting;
SELECT
query_id,
query_text,
doc_id,
title,
category,
content,
distance,
ROW_NUMBER() OVER (
PARTITION BY query_id
ORDER BY distance ASC
) AS rank_no
FROM (
SELECT
query.query_id AS query_id,
query.query_text AS query_text,
base.doc_id AS doc_id,
base.title AS title,
base.category AS category,
base.content AS content,
distance
FROM VECTOR_SEARCH(
(
SELECT
doc_id,
title,
category,
content,
text_embedding
FROM text_search_corpus
WHERE text_embedding IS NOT NULL
) base,
text_embedding,
(
SELECT
query_id,
query_text,
query_embedding
FROM text_search_query
WHERE query_embedding IS NOT NULL
) query,
query_embedding,
3,
Cosine
)
) search_result
ORDER BY query_id, rank_no;
-- 返回结果:
+----------+----------------------------------------------------------------+--------+------------------+----------+------------------------------------------------------------------------------+---------------------+------------+
| query_id | query_text | doc_id | title | category | content | distance | rank_no |
+----------+----------------------------------------------------------------+--------+------------------+----------+------------------------------------------------------------------------------+---------------------+------------+
| Q001 | 周末想带孩子在杭州找一个能亲近自然又不太累的地方 | T001 | 西溪湿地亲子观鸟 | 旅行 | 西溪湿地水网密布,步道平缓,春秋两季适合家长带孩子观察水鸟和湿地植物,半天即可完成主要路线。 | 0.25343477725982666 | 1 |
| Q001 | 周末想带孩子在杭州找一个能亲近自然又不太累的地方 | T004 | 良渚文化一日参观 | 旅行 | 上午参观良渚博物院了解文明起源,下午前往遗址公园体验考古场景,建议提前预约并准备防晒用品。 | 0.39122873544692993 | 2 |
| Q001 | 周末想带孩子在杭州找一个能亲近自然又不太累的地方 | T002 | 西湖清晨慢行路线 | 旅行 | 从断桥沿北山街步行到曲院风荷,清晨游客较少,路线平坦,适合希望轻松欣赏湖景的人群。 | 0.4272348880767822 | 3 |
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | H026 | 小户型功能分区 | 家居 | 可通过地毯、矮柜和灯光划分工作与休息区域,避免使用厚重隔断,让采光和通行保持连续。 | 0.34322673082351685 | 1 |
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | H025 | 书桌线缆整理 | 家居 | 将插线板固定在桌下,用理线夹区分电源线和数据线,并为经常插拔的线材保留适当余量。 | 0.3543819189071655 | 2 |
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | D020 | 视频会议减少环境噪声 | 数码 | 优先使用带麦克风的耳机,关闭房间内持续噪声源,并在会议软件中开启回声消除和降噪功能。 | 0.37590378522872925 | 3 |
| Q003 | 刚把小猫接回家,需要先买哪些用品 | P031 | 新猫到家用品清单 | 宠物 | 接猫前应准备猫砂盆、猫砂、食盆、饮水碗、适龄主粮、猫抓板和安全的躲藏空间,先让它安静适应。 | 0.26469898223876953 | 1 |
| Q003 | 刚把小猫接回家,需要先买哪些用品 | P035 | 减少猫抓家具 | 宠物 | 在猫经常停留和抓挠的位置放置稳定的猫抓板,通过玩具和奖励引导使用,不要只靠驱赶。 | 0.3960789442062378 | 2 |
| Q003 | 刚把小猫接回家,需要先买哪些用品 | P032 | 鼓励猫咪多喝水 | 宠物 | 可以把水碗远离食盆和猫砂盆,分散放置多个饮水点,并保持每天换水,部分猫更喜欢流动水。 | 0.40927886962890625 | 3 |
+----------+----------------------------------------------------------------+--------+------------------+----------+------------------------------------------------------------------------------+---------------------+------------+
VECTOR_SEARCH 不保证原始输出顺序,因此本文根据 distance 显式生成查询内排名。使用 cosine 距离时,数值越小表示向量越接近。
预期结果: 每条 Query 返回 3 条结果,并按 distance 从小到大排列。通常可以观察到:
Q001优先召回杭州、西溪湿地、亲子自然体验或轻松步行相关内容。Q002召回居家办公空间、家庭网络、视频会议或桌面整理相关内容。Q003优先召回新猫到家用品、猫砂盆、主粮或猫咪适应环境相关内容。
实际排序会受到模型版本和向量结果影响,不要求标题和上述说明完全一致。重点检查 Top 3 是否与 Query 的语义相关。
use_brute_force 的默认值为 false,系统可以使用可用的向量索引。如果没有可用索引,系统仍可能回退为暴力检索。仅返回结果不能证明本次任务一定命中索引。
步骤六:使用标量条件缩小检索范围
实际搜索通常既包含语义条件,也包含类目、状态、地域或时间等标量条件。VECTOR_SEARCH 支持将子查询作为候选内容表,因此可以先通过普通 SQL 条件缩小候选范围,再计算向量距离。
以下示例使用 Q002 搜索居家办公相关内容,但只允许从“数码”和“家居”两个类目中返回结果:
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
SELECT
query.query_id AS query_id,
query.query_text AS query_text,
base.doc_id AS doc_id,
base.title AS title,
base.category AS category,
base.content AS content,
distance
FROM VECTOR_SEARCH(
(
SELECT
doc_id,
title,
category,
content,
text_embedding
FROM text_search_corpus
WHERE category IN ('数码', '家居')
AND text_embedding IS NOT NULL
) base,
text_embedding,
(
SELECT
query_id,
query_text,
query_embedding
FROM text_search_query
WHERE query_id = 'Q002'
AND query_embedding IS NOT NULL
) query,
query_embedding,
3,
Cosine
)
ORDER BY distance ASC;
-- 预期结果category 只能是“数码”或“家居”:
-- 通常可以同时观察到家庭网络、视频会议等数码内容,以及桌面整理、空间布置等家居内容。具体顺序以模型生成的向量为准。
-- 返回结果如下:
+----------+---------------------------------------------------------------+--------+-------------------+----------+------------------------------------------------------------------------+--------------------+
| query_id | query_text | doc_id | title | category | content | distance |
+----------+---------------------------------------------------------------+--------+-------------------+----------+------------------------------------------------------------------------+--------------------+
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | H026 | 小户型功能分区 | 家居 | 可通过地毯、矮柜和灯光划分工作与休息区域,避免使用厚重隔断,让采光和通行保持连续。 | 0.34322673082351685 |
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | H025 | 书桌线缆整理 | 家居 | 将插线板固定在桌下,用理线夹区分电源线和数据线,并为经常插拔的线材保留适当余量。 | 0.3543819189071655 |
| Q002 | 准备长期在家办公,怎样把工作区布置得整洁舒适,同时保证上网和开会不掉链子? | D020 | 视频会议减少环境噪声 | 数码 | 优先使用带麦克风的耳机,关闭房间内持续噪声源,并在会议软件中开启回声消除和降噪功能。 | 0.37590378522872925 |
+----------+---------------------------------------------------------------+--------+-------------------+----------+------------------------------------------------------------------------+---------------------+两个子查询承担不同职责:
base 子查询中的
category IN ('数码', '家居')限定“到哪些内容中搜索”。query 子查询中的
query_id = 'Q002'限定“本次使用哪条 Query 搜索”。
标量条件应放在 base 子查询中,使 Top 3 从符合条件的候选内容中产生。如果先对全库执行 Top 3,再在外层过滤类目,可能导致部分结果被删除,最终不足 3 条,也可能遗漏受限类目中原本更相关的内容。
验证结果
完成全部步骤后,检查以下项目:
数据完整:文本总数、唯一
doc_id数和非空向量数是否均为 60。索引可用:索引状态是否为
ACTIVE,覆盖率是否为100%。数量正确:每条 Query 是否返回 3 条结果。
排序正确:同一 Query 的结果是否按
distance升序排列。语义相关:Top 3 是否围绕 Query 意图,而不只是出现相同关键词。
过滤有效:标量过滤结果是否全部属于“数码”或“家居”。
向量距离不是业务置信度,也不存在适用于所有数据集的固定阈值。更换模型、维度或文本预处理方式后,应重新生成文本库和 Query 向量,并重建索引。
清理资源
如果不再需要本教程创建的资源,可以执行以下 SQL 删除索引和示例表。
删除后数据不可恢复。请确认这些对象不再使用,并避免在包含其他业务数据的表上执行以下命令。
SET odps.namespace.schema=true;
SET odps.sql.type.system.odps2=true;
SET odps.sql.type.vector.enable=true;
DROP INDEX idx_text_search_corpus_embedding
ON text_search_corpus;
DROP TABLE IF EXISTS text_search_query;
DROP TABLE IF EXISTS text_search_corpus;
后续步骤
了解模型调用参数和返回值,请参见 AI_EMBEDDING。
了解向量类型、维度和限制,请参见 VECTOR数据类型。
了解索引的创建、重建、查看和删除,请参见 VECTOR INDEX。
了解检索参数、返回值和索引回退行为,请参见 VECTOR_SEARCH。
了解表格式及其能力,请参见 Delta Table概述。
了解支持地域、模型和费用,请参见 购买与使用MaxCompute 模型计算服务。