news 2026/9/10 11:37:55

agno 图像标注到向量数据库:用 Agent 抽取结构化描述并构建可搜索媒体库的完整管线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
agno 图像标注到向量数据库:用 Agent 抽取结构化描述并构建可搜索媒体库的完整管线

agno 图像标注到向量数据库:用 Agent 抽取结构化描述并构建可搜索媒体库的完整管线

【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno

导读

本文以 agno cookbook 中的_09_image_extraction_to_vectordb示例为骨架,完整讲解"图像标注 → 向量化 → 检索"的端到端管线:一个 Agent 从图片 URL 中抽取结构化ImageDescription(主体、场景、氛围、关键物体),把结构化字段展平为可搜索文本,再用GeminiEmbedder嵌入并写入 LanceDb,最终支持用自然语言查询相似图片。读完本文,你将掌握在 agno 中搭建"可搜索媒体库 / 以文搜图 / 找相似"类标注管线的完整实操方法与底层原理,并看到该管线在真实环境中的测试验证结果。

该示例位于 cookbook/data_labeling/_09_image_extraction_to_vectordb,核心实现文件为 basic.py,配套说明见 README.md。本文所有结论均依据仓库中的文档与源码。


一、示例定位:一条完整而非片段化的标注工作流

在 agno 的 data_labeling 系列 cookbook 中,_09_image_extraction_to_vectordb的价值恰恰在于它是完整的端到端管线,而不是某一个环节的单独演示。README 明确指出:basic.py把"extract → embed → store → search"四个步骤浓缩在一个文件里,没有额外变体,价值在于完整管线本身

管线的四个环节:

  1. 对每张图片 URL,用一个 Agent 抽取结构化的ImageDescription(subject 主体、setting 场景、mood 氛围、key_objects 关键物体);
  2. 将结构化字段展平为单条可搜索文本;
  3. GeminiEmbedder对文本做嵌入,存入 LanceDb;
  4. 用自然语言查询检索索引,返回最相似的图片。

值得强调的一点(README 中专门提醒):该检索作用于抽取出的文本描述,而非图像本身的嵌入——两张图片匹配,是因为它们的描述文本匹配。这决定了它适合的落地场景:

  • 用自然语言查询搜索图库(stock photo library);
  • 按描述相似度对商品目录去重(注意:去重依据是抽取出的文本描述);
  • 在用户上传的媒体上构建"find more like this"(找相似)功能。

二、快速运行:环境准备与执行命令

运行该示例只需要两步(来自 README.md):

pip install lancedb python cookbook/data_labeling/_09_image_extraction_to_vectordb/basic.py

运行前提与产物:

  • API Key:需要GOOGLE_API_KEY环境变量。在源码层面,GeminiEmbedder 在构建客户端时通过getenv("GOOGLE_API_KEY")读取该变量,未设置时会记录错误日志GOOGLE_API_KEY not set。此外也可通过GOOGLE_GENAI_USE_VERTEXAI=true切换到 Vertex AI 方式(此时读取GOOGLE_CLOUD_PROJECTGOOGLE_CLOUD_LOCATION)。
  • 数据目录:运行会写入仓库根目录下的tmp/lancedb/。LanceDb 默认uri="/tmp/lancedb",示例显式传入uri="tmp/lancedb"(相对路径,落在仓库根)。
  • 可选依赖说明:TEST_LOG 实测确认,未安装tantivy也能正常运行——因为本例只使用SearchType.vector(向量检索),关键字检索引擎tantivy仅在 keyword/hybrid 检索时需要。

三、核心代码逐段拆解(basic.py)

3.1 结构化输出 Schema:ImageDescription

抽取 Agent 的输出不是自由文本,而是一个 Pydantic 模型,四个字段各带描述(basic.py):

class ImageDescription(BaseModel): subject: str = Field(..., description="The main subject of the image") setting: str = Field(..., description="Where the image takes place") mood: str = Field(..., description="Overall mood or tone") key_objects: List[str] = Field( default_factory=list, description="Up to five notable objects" )
  • subject:图片主体;
  • setting:图片发生场景/地点;
  • mood:整体氛围或基调;
  • key_objects:最多五个值得注意的物体(默认空列表)。

用 Pydantic 模型做output_schema,是 agno 结构化输出的标准做法——模型必须按该 Schema 返回,才能被后续步骤可靠地展平与入库。

3.2 抽取 Agent

extractor = Agent( model="google:gemini-3.5-flash", instructions="You describe images as structured, search-friendly metadata.", output_schema=ImageDescription, )
  • 模型使用google:gemini-3.5-flash
  • 指令明确要求"把图片描述成结构化、便于搜索的元数据"——提示词与 Schema 双管齐下,确保输出是"搜索友好"的元数据而非散文;
  • output_schema=ImageDescription让每次run.content直接是ImageDescription实例。

3.3 向量数据库:LanceDb + GeminiEmbedder

vector_db = LanceDb( uri="tmp/lancedb", table_name="data_labeling_images", search_type=SearchType.vector, embedder=GeminiEmbedder(id="gemini-embedding-001"), )

对应 agno 的 LanceDb 实现,关键点:

  • uri:LanceDB 数据库位置,示例用本地相对路径;
  • table_name:表名data_labeling_images,表已存在时打开,不存在则后续创建;
  • search_type:取自 agno.vectordb.search.SearchType,可选vector(向量检索,本例所用)、keyword(关键字检索)、hybrid(混合检索);
  • embedder:默认值为OpenAIEmbedder(源码中未传时会回退并打印提示),本例显式指定GeminiEmbedder(id="gemini-embedding-001")
  • 其他可配置项(源码可见,便于按需扩展):distance(默认Distance.cosine,余弦距离)、nprobes(检索探针数)、reranker(重排器)、on_bad_vectors(坏向量处理策略:error/drop/fill/null)与fill_value

GeminiEmbedder 的关键默认值:模型id="gemini-embedding-001"task_type="RETRIEVAL_QUERY"dimensions=1536,并支持通过request_params/client_params透传额外参数。嵌入请求通过 Google GenAI 客户端的models.embed_content完成(google.py),output_dimensionalitytask_type均会随请求发送。值得注意:LanceDb 构造时会校验Embedder.dimensions必须已设置,否则抛ValueError(lance_db.py)——GeminiEmbedder默认dimensions=1536,满足此约束。

3.4 管线函数:describe / to_searchable_text / index_images

三个函数共同构成管线主体(basic.py):

def describe(url: str) -> ImageDescription: return extractor.run("Describe this image.", images=[Image(url=url)]).content def to_searchable_text(d: ImageDescription) -> str: return ( f"Subject: {d.subject}. Setting: {d.setting}. Mood: {d.mood}. " f"Objects: {', '.join(d.key_objects)}." ) def index_images(urls: List[str]) -> None: vector_db.create() docs: List[Document] = [] for url in urls: description = describe(url) docs.append( Document( name=url, content=to_searchable_text(description), meta_data={"url": url, "subject": description.subject}, ) ) vector_db.insert(content_hash="image_batch_1", documents=docs)
  • describe:把图片 URL 包装为agno.media.Image(url=url),随提示词一起交给 Agent,返回结构化描述;
  • to_searchable_text:把四个字段拼接成单一可检索文本——这是"把结构化输出变成可搜索文本"的关键一步,也是 README 强调"检索作用于文本描述"的直接体现;
  • index_images:先vector_db.create()建表,再对每张图抽取、构造Documentname用图片 URL,content用展平文本,meta_data附带 url 与 subject 便于检索后回看元信息),最后以content_hash="image_batch_1"为批次标识整体插入。Document对应 agno/knowledge/document/base.py 中的核心数据结构。

3.5 主流程:三张示例图 + 两条自然语言查询

if __name__ == "__main__": urls = [ "https://agno-public.s3.amazonaws.com/images/krakow_mariacki.jpg", "https://www.gstatic.com/webp/gallery/1.jpg", "https://storage.googleapis.com/generativeai-downloads/images/generated_elephants_giraffes_zebras_sunset.jpg", ] index_images(urls) for query in ["a historic city at night", "wildlife on the savanna"]: results = vector_db.search(query, limit=2) pprint({"query": query, "hits": [r.meta_data for r in results]})
  • 三张图片:克拉科夫圣母圣殿(城市夜景主题)、gstatic 图库样例、大象/长颈鹿/斑马/鳄鱼汇聚水塘的野生动物场景;
  • vector_db.search(query, limit=2):以自然语言查询向量索引,返回前 2 条命中;
  • 结果打印各命中的meta_data(含 url 与 subject),方便对照。

四、实测验证:TEST_LOG 的端到端结果

仓库中的 TEST_LOG.md 记录了 2026-07-18 在gemini-3.5-flash+gemini-embedding-001(embedder)、agno 2.7.4 环境下的实测结论,可作为该管线的可信度佐证:

  • 运行方式:删除tmp/lancedb/后从干净状态跑完整管线;
  • 抽取质量:三张图全部成功产出结构规整的输出。例如克拉科夫图得到 subject "St. Mary's Basilica framed by the arches of the Cloth Hall"(圣玛丽大教堂与纺织会馆拱门同框)、mood "Magical and serene"(魔幻而宁静);野生动物图得到 subject "A diverse group of African wildlife, including elephants, giraffes, zebras, and a crocodile, gathered at a watering hole"(多种非洲野生动物汇聚水塘);
  • 写入结果:3 条文档成功插入;
  • 检索正确性:查询 "a historic city at night" 命中克拉科夫圣母圣殿;查询 "wildlife on the savanna" 命中大象/长颈鹿/斑马场景——两条查询均返回语义正确的最相似图片;
  • 性能参考:单张图片抽取耗时约 2.7–4.8 秒(该值依赖模型与网络,仅作参考,不作为普遍性能承诺);
  • 环境边界:未安装tantivy也能跑通,再次印证向量检索不依赖关键字引擎。

五、从源码看底层工作方式:为什么这条管线成立

  1. 结构化输出的可靠性output_schema+ 指令双约束,使 Agent 的输出稳定落在ImageDescription上,从而可以机械地展平为检索文本——这是后续一切的前提。
  2. 嵌入与维度一致性GeminiEmbedder固定输出 1536 维(dimensions默认值),LanceDb 构造时校验embedder.dimensions已设置(lance_db.py),保证建表时向量维度与嵌入结果一致;检索默认使用余弦距离(Distance.cosine)。
  3. 文本检索而非图像检索:整个流程中 LanceDb 存的是"描述文本的嵌入",查询时search(query)内部同样先对查询文本做嵌入再比对。因此召回质量取决于抽取出的描述质量——这也解释了为何指令要强调"search-friendly metadata"。
  4. 可扩展配置:如需混合检索,可把search_type改为SearchType.hybrid(此时需安装tantivy);如需云上 LanceDB,可传api_key=或设置LANCEDB_API_KEY(源码对db://开头的 Cloud URI 强制要求 API Key,见 lance_db.py);如需切换 Embedder,直接替换embedder=参数即可。

六、延伸阅读

  • 同系列标注管线入口:cookbook/data_labeling/README.md,可对比文本、图像、音频、视频、文档等各模态的标注与抽取方案;
  • 向量存储的其他后端示例:cookbook/06_storage(MySQL、Postgres、SQLite、Redis、Mongo 等);LanceDb 源码实现在 libs/agno/agno/vectordb/lancedb/lance_db.py,Embedder 抽象在 libs/agno/agno/knowledge/embedder/base.py,GeminiEmbedder在 libs/agno/agno/knowledge/embedder/google.py;
  • 若需要构建 Agent 自身的知识检索(RAG),可参考 cookbook/07_knowledge 中的向量库接入方式。

【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 11:37:07

TVBoxOSC 电视盒子控制使用完全指南:从安装到流畅播放的完整路线

TVBoxOSC 电视盒子控制使用完全指南:从安装到流畅播放的完整路线 【免费下载链接】TVBoxOSC TVBoxOSC - 一个基于第三方项目的代码库,用于电视盒子的控制和管理。 项目地址: https://gitcode.com/GitHub_Trending/tv/TVBoxOSC 晚上想看点片&#…

作者头像 李华
网站建设 2026/9/10 11:36:39

Python自行车共享需求预测实战:从数据清洗到可解释回归

简介:本资源是一份面向数据科学初学者与计算机相关专业学生的Kaggle实战项目,聚焦城市自行车共享系统使用状况的探索性分析与需求预测,适用于毕业设计、课程设计及算法入门实践。压缩包共8个文件,含3个核心数据集(CSV&…

作者头像 李华
网站建设 2026/9/10 11:25:33

PixWit:轻量高效的开发者截图录屏工具解析

1. PixWit工具定位与核心价值程序员在日常工作中经常需要处理各种截图、录屏需求:可能是记录Bug现象、制作技术演示、编写文档配图,或是与团队成员快速共享界面状态。传统做法需要同时打开多个工具——用Snipaste截图、OBS录屏、再用剪映简单剪辑&#x…

作者头像 李华