公司动态

LLM Agent驱动的艺术图像隐式语义标注:ArtAnno框架解析

📅 2026/8/27 13:36:01
LLM Agent驱动的艺术图像隐式语义标注:ArtAnno框架解析
艺术图像标注一直是数字人文、计算机视觉与信息检索领域一个比较难啃的方向。早期标注系统大多围绕外显语义展开——画面里有什么物体、什么颜色、什么构图这些“看得见”的信息很容易结构化。但真正有研究价值的往往是“看不见”的部分画家想表达什么情绪作品在特定历史语境下的象征含义画面元素背后的隐喻。这类语义被称为隐式语义Implicit Semantics人工标注成本高、主观性强普通算法又难以建模。最近读到一个很有意思的研究框架 ArtAnno它用 LLM Agent 驱动的方式重新设计了艺术图像标注流程核心思路叫“双向人机增强”Bidirectional Human-AI Augmentation。本文围绕这个项目拆解它的系统设计、核心模块和工程实现思路并给出可落地的代码示例。1. 背景与核心概念1.1 艺术图像标注的难点在哪里先来看一个短视频平台的用户投稿场景系统需要给一张文艺复兴时期的宗教画打标签用来做内容推荐和知识库分类。传统标签体系会输出“油画”“人物”“宗教”“文艺复兴”这类显式标签这种标注粒度对现代 LLM 来说基本没有难度。但如果希望标签能表达“画面的悲伤感”“人物姿态暗示的从众心理”“作品对当时政治环境的隐喻”就涉及了隐式语义。隐式语义有三个典型特点高度主观性。同一幅画不同文化背景的人解读差异非常大。依赖外部知识。要理解画作中的符号往往需要了解神话故事、宗教背景、作者生平、历史事件。难以枚举。显式标签可以通过预定义类别解决隐式语义几乎是开放集合问题。如果用传统的硬规则标注方法很难适应这种灵活性。这也是 ArtAnno 选择 LLM Agent 驱动的原因——大语言模型具备强大的常识推理和知识联想能力天然适合生成开放式的语义解释。1.2 什么是 ArtAnnoArtAnno 是一个面向艺术图像隐式语义标注的研究框架。它不试图训练一个新的图像理解模型而是借助 LLM Agent 的规划与推理能力把“图像内容”和“外部知识”串起来形成一条可解释的标注链路。项目全称中的几个关键词值得拆开理解关键词含义ArtAnnoArt Annotation 的缩写艺术标注系统Implicit Semantics隐式语义区别于显式标签的深层含义LLM Agent-Driven用大模型代理驱动的任务编排方式Bidirectional Human-AI Augmentation双向人机增强AI 辅助人人也反过来增强 AI1.3 双向人机增强是什么“双向增强”是 ArtAnno 的设计核心可以理解成两条互补的链路AI 辅助人类AI→HumanLLM Agent 自动从画作中提取视觉元素结合外部知识库生成隐式语义标注候选和建议。人工只需审核、修正或补充大大降低标注启动成本。人类增强 AIHuman→AI人的修正反馈被记录下来形成高质量标注样本。这些样本沉淀到知识库中后续 Agent 在生成标注时会优先参考相当于持续微调模型的“上下文记忆”。这种设计比单纯让 LLM 自动标注更可靠也比纯人工标注更高效形成了数据飞轮效应。2. 系统架构与核心设计2.1 整体架构ArtAnno 的架构可以拆成五个层次输入层艺术图像 基础元数据 ↓ 视觉理解层多模态模型 / 视觉特征提取 ↓ 知识层外部知识库、艺术史语料、历史标注沉淀 ↓ Agent 推理层LLM Agent 编排标注任务 ↓ 输出层结构化隐式语义标注 置信度 可解释依据输入层不只是图像本身还包括艺术家、年代、流派等基础元数据。这些信息可以帮助 LLM 缩小推理范围。视觉理解层负责把图像转换成文本可用的视觉描述比如画面元素、色彩分布、构图关系。知识层为 Agent 提供外部知识和历史标注数据。Agent 推理层是核心它通过多轮推理生成隐式语义解释。输出层则负责把结果格式化为结构化数据便于入库和检索。2.2 Agent 驱动的工作流程ArtAnno 的 Agent 不是简单的“调用一次大模型然后返回结果”而是一个多阶段的任务编排流程。整个标注过程可以拆成几个步骤场景识别Agent 先判断图像类型是宗教画、肖像画、风景画还是抽象表现主义作品。视觉元素提取调用多模态模型获取画面中可观察的元素清单。知识检索基于视觉元素和元数据从知识库中检索相关背景信息。隐式语义推断综合视觉信息和知识信息生成候选语义标注。合理性自检Agent 对每一条标注进行自评判断是否有依据、是否过度解读。人工审核反馈结果进入人机协同界面由人工确认或修改。这个流程的编排逻辑在代码层面可以抽象为一个状态机或一个任务队列后面我们会在实战部分给出实现思路。3. 环境准备与版本说明版本需要根据你的项目实际情况调整下面以常见环境为例重点演示配置思路。3.1 基础环境依赖建议版本/说明Python3.10操作系统Ubuntu 20.04 / macOS / WindowsWSL2LLM APIOpenAI、智谱、千问等兼容 OpenAI 格式的接口视觉模型GPT-4V、Qwen-VL、InternVL 等框架LangChain 或自研 Agent 调度框架这里不限定具体模型因为 ArtAnno 的思路是 Agent 编排 多模型协同模型本身可以替换。设计时要尽量兼容 OpenAI 格式的 API方便切换供应商。3.2 项目结构artanno/ ├── agent/ │ ├── orchestrator.py # 任务编排核心 │ ├── steps/ # 各阶段处理步骤 │ ├── prompts/ # 提示词模板 │ └── memory/ # 反馈记忆模块 ├── knowledge/ │ ├── loader.py # 知识库加载 │ └── retriever.py # 知识检索 ├── vision/ │ ├── describer.py # 视觉描述模块 │ └── adapter.py # 多模态模型适配 ├── api/ │ ├── main.py # 标注服务接口 │ └── schemas.py # 数据模型 ├── data/ │ ├── artworks/ # 艺术图像目录 │ └── annotations/ # 标注输出目录 └── requirements.txt3.3 安装依赖pip install openai langchain langchain-openai pip install pydantic fastapi uvicorn pip install python-dotenv考虑到不同环境的网络情况如果无法直接安装依赖也可以使用国内镜像源。4. 核心模块代码实现这一部分我们重点拆解 ArtAnno 的几个核心模块视觉描述模块、Agent 编排模块、知识检索模块和反馈记忆模块。4.1 视觉描述模块ArtAnno 首先需要把图像转化为文本描述。这里我们设计一个ArtworkDescriber它使用多模态模型生成结构化的视觉描述方便后续 LLM Agent 推理。# 文件路径artanno/vision/describer.py from openai import OpenAI import base64 import os from typing import Dict, List class ArtworkDescriber: 基于多模态大模型的艺术图像视觉描述模块 def __init__(self, model_name: str gpt-4o): self.client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) self.model_name model_name staticmethod def encode_image(image_path: str) - str: 将本地图像编码为 Base64 字符串 with open(image_path, rb) as f: return base64.b64encode(f.read()).decode(utf-8) def describe(self, image_path: str, metadata: Dict[str, str]) - Dict[str, object]: 生成结构化视觉描述 :param image_path: 图像本地路径 :param metadata: 艺术图像元数据标题、作者、年代等 :return: 包含视觉元素的描述字典 base64_image self.encode_image(image_path) prompt f 你是艺术史研究员。请根据以下作品信息观察图像生成结构化的视觉描述。 作品信息 标题{metadata.get(title, 未知)} 作者{metadata.get(artist, 未知)} 年代{metadata.get(date, 未知)} 流派{metadata.get(genre, 未知)} 请按以下 JSON 格式输出 {{ objects: [画面中出现的物体], colors: [主色调], composition: 构图描述, figures: [人物或主体], styles: [风格特征] }} response self.client.chat.completions.create( modelself.model_name, messages[ { role: user, content: [ {type: text, text: prompt}, { type: image_url, image_url: { url: fdata:image/jpeg;base64,{base64_image} } } ] } ], temperature0.2 ) text response.choices[0].message.content return self._parse_response(text) staticmethod def _parse_response(text: str) - Dict[str, object]: 解析模型返回的 JSON 字符串 实际应用中建议使用 JSON Mode 或函数调用 import json try: return json.loads(text) except json.JSONDecodeError: return { objects: [], colors: [], composition: text[:100], figures: [], styles: [] }实际开发中视觉模型的输出格式不稳定建议使用 OpenAI 的response_format{type: json_object}或者 Function Calling 来保证 JSON 输出。4.2 知识检索模块隐式语义推断不能只依赖图像信息。ArtAnno 会先从知识库中检索与作品相关的背景知识再把知识上下文注入 LLM。这里用一个简单的向量检索模块作为示例。# 文件路径artanno/knowledge/retriever.py import os from typing import List, Dict from openai import OpenAI class KnowledgeRetriever: 知识检索模块基于向量相似度召回背景知识 def __init__(self, model_name: str text-embedding-3-small): self.client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) self.model_name model_name # 实际场景中建议使用 Chroma、FAISS 等向量数据库 self.knowledge_base [] self.index [] def add_documents(self, docs: List[str]): 向知识库中批量添加文档 embeddings self._embed(docs) self.knowledge_base.extend(docs) self.index.extend(embeddings) def _embed(self, texts: List[str]) - List[List[float]]: resp self.client.embeddings.create( modelself.model_name, inputtexts ) return [item.embedding for item in resp.data] def search(self, query: str, top_k: int 5) - List[str]: 根据查询召回最相关的知识片段 import numpy as np if not self.knowledge_base: return [] query_vec self._embed([query])[0] similarities [] for vec in self.index: score self._cosine_similarity(query_vec, vec) similarities.append(score) top_indices np.argsort(similarities)[-top_k:][::-1] return [self.knowledge_base[i] for i in top_indices] staticmethod def _cosine_similarity(a: List[float], b: List[float]) - float: import numpy as np vec_a np.array(a) vec_b np.array(b) return float(vec_a vec_b / (np.linalg.norm(vec_a) * np.linalg.norm(vec_b)))这里省略了向量数据库的持久化逻辑生产环境建议使用 Chroma 或 FAISS 管理索引并定时更新知识库。4.3 Agent 编排模块Agent 编排模块是 ArtAnno 的核心它负责任务拆分、步骤调度和结果整合。下面用 LangChain 的 Agent 框架实现一个简化的编排器。# 文件路径artanno/agent/orchestrator.py from typing import Dict, List, Any from openai import OpenAI from langchain.prompts import ChatPromptTemplate from langchain.output_parsers import ResponseSchema, StructuredOutputParser import os import json class ArtAnnoOrchestrator: ArtAnno 的 Agent 编排器 职责 1. 根据视觉描述和背景知识规划标注任务 2. 执行隐式语义推断 3. 做自检与修正 def __init__(self, vision_describer, knowledge_retriever): self.vision vision_describer self.knowledge knowledge_retriever self.client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) self.model_name os.getenv(LLM_MODEL, gpt-4o) def annotate(self, image_path: str, metadata: Dict[str, str]) - Dict[str, Any]: 执行完整标注流程 :param image_path: 图像路径 :param metadata: 元数据 :return: 标注结果 # Step 1: 视觉描述抽取 visual self.vision.describe(image_path, metadata) print([ArtAnno] 视觉描述完成:, visual) # Step 2: 知识检索 query f{metadata.get(title, )} {metadata.get(artist, )} {visual.get(objects, [])} knowledge_docs self.knowledge.search(query, top_k5) print([ArtAnno] 命中知识片段数:, len(knowledge_docs)) # Step 3: 隐式语义推断 semantics self._infer_semantics(visual, metadata, knowledge_docs) # Step 4: 自检与修正 refined self._self_refine(visual, semantics, knowledge_docs) return { metadata: metadata, visual_description: visual, implicit_semantics: refined, knowledge_sources: knowledge_docs } def _infer_semantics( self, visual: Dict, metadata: Dict[str, str], knowledge_docs: List[str] ) - List[Dict[str, str]]: 隐式语义推断 :return: 语义标注列表 prompt f 你是一名艺术史学者请根据以下信息为一幅艺术作品生成隐式语义标注。 作品基本信息 - 标题{metadata.get(title, 未知)} - 作者{metadata.get(artist, 未知)} - 年代{metadata.get(date, 未知)} - 流派{metadata.get(genre, 未知)} 视觉描述 {json.dumps(visual, ensure_asciiFalse, indent2)} 背景知识 {chr(10).join(knowledge_docs) if knowledge_docs else 暂无额外知识} 请生成 3-5 条隐式语义标注每条包含 1. aspect分析维度情感、象征、历史语境、文化隐喻等 2. annotation具体语义解读 3. evidence支撑依据来自画面或知识库 4. confidence置信度0-1之间 请以 JSON 数组格式输出。 response self.client.chat.completions.create( modelself.model_name, messages[{role: user, content: prompt}], temperature0.7, response_format{type: json_object} ) text response.choices[0].message.content result json.loads(text) return result.get(annotations, result) def _self_refine( self, visual: Dict, semantics: List[Dict[str, str]], knowledge_docs: List[str] ) - List[Dict[str, str]]: 自检与修正过滤过度解读保留有依据的标注 prompt f 以下是对一幅艺术图像的隐式语义标注候选。请结合画面证据和背景知识 筛选出最合理的条目去掉明显过度解读或缺乏依据的条目。 标注候选 {json.dumps(semantics, ensure_asciiFalse, indent2)} 请只输出 JSON 数组数组元素包含 aspect、annotation、evidence、confidence 字段。 response self.client.chat.completions.create( modelself.model_name, messages[{role: user, content: prompt}], temperature0.2 ) text response.choices[0].message.content try: result json.loads(text) return result except json.JSONDecodeError: # 如果解析失败返回原有结果而不是报错 return semantics4.4 反馈记忆模块ArtAnno 的“人类增强 AI”能力依赖反馈记忆模块。人工审核后的标注会被保存为“经验样本”后续标注任务中作为示例参考。这里用简单的文件存储实现。# 文件路径artanno/agent/memory/feedback_memory.py import json import os from typing import Dict, List from datetime import datetime class FeedbackMemory: 人工反馈记忆模块 记录人工审核后的高质量标注在后续标注中作为 few-shot 示例使用。 生产环境建议替换为数据库或向量存储。 def __init__(self, storage_path: str data/annotations/feedback.jsonl): self.storage_path storage_path os.makedirs(os.path.dirname(storage_path), exist_okTrue) def save_feedback(self, entry: Dict): 保存人工确认后的标注 entry[timestamp] datetime.now().isoformat() with open(self.storage_path, a, encodingutf-8) as f: f.write(json.dumps(entry, ensure_asciiFalse) \n) def load_examples(self, limit: int 5) - List[Dict]: 加载历史标注作为示例 if not os.path.exists(self.storage_path): return [] examples [] with open(self.storage_path, r, encodingutf-8) as f: for line in f: line line.strip() if line: examples.append(json.loads(line)) return examples[-limit:] def build_few_shot_prompt(self, limit: int 3) - str: 构建 few-shot 提示词片段 examples self.load_examples(limit) if not examples: return 暂无历史标注参考。 prompt_lines [] for idx, ex in enumerate(examples): prompt_lines.append(f示例 {idx 1}:) prompt_lines.append(f标题: {ex.get(metadata, {}).get(title, 未知)}) prompt_lines.append(f隐式语义: {json.dumps(ex.get(implicit_semantics, []), ensure_asciiFalse)}) prompt_lines.append() return \n.join(prompt_lines)这样下一次 Agent 推断时会先加载历史高置信度标注作为参考标注质量会随使用次数上升。5. 完整实战案例下面用一个简化案例串起所有模块演示 ArtAnno 从图像输入到标注输出的完整流程。5.1 准备测试数据在项目根目录下创建data/artworks/放入一张测试艺术图像并创建对应的元数据# 文件路径demo.py from artanno.vision.describer import ArtworkDescriber from artanno.knowledge.retriever import KnowledgeRetriever from artanno.agent.orchestrator import ArtAnnoOrchestrator from artanno.agent.memory.feedback_memory import FeedbackMemory import os # 读取环境变量 from dotenv import load_dotenv load_dotenv() image_path data/artworks/test_painting.jpg metadata { title: The Persistence of Memory, artist: Salvador Dali, date: 1931, genre: Surrealism } # 初始化模块 describer ArtworkDescriber() retriever KnowledgeRetriever() # 向知识库中添加一些背景知识 retriever.add_documents([ 萨尔瓦多·达利是西班牙超现实主义画家以梦境般的画面著称。, 《记忆的永恒》The Persistence of Memory创作于1931年画面中的软表象征时间的相对性与无意义。, 超现实主义运动深受弗洛伊德精神分析理论影响强调潜意识与梦境。, 画作中的怪物形象被认为是艺术家的自画像暗示个体内心的恐惧与焦虑。 ]) orchestrator ArtAnnoOrchestrator(describer, retriever) memory FeedbackMemory() # 执行标注 result orchestrator.annotate(image_path, metadata) # 输出结果 print(\n ArtAnno 标注结果 ) print(元数据:, result[metadata]) print(\n视觉描述:) for k, v in result[visual_description].items(): print(f {k}: {v}) print(\n隐式语义标注:) for item in result[implicit_semantics]: print(f - 维度: {item.get(aspect)}) print(f 解读: {item.get(annotation)}) print(f 依据: {item.get(evidence)}) print(f 置信度: {item.get(confidence)}) # 模拟人工审核后保存反馈 memory.save_feedback({ metadata: metadata, implicit_semantics: result[implicit_semantics] })5.2 运行与预期结果python demo.py正常运行时会看到类似下面的输出[ArtAnno] 视觉描述完成: {objects: [clock, landscape, strange creature], ...} [ArtAnno] 命中知识片段数: 4 ArtAnno 标注结果 元数据: {title: The Persistence of Memory, ...} 视觉描述: objects: [clock, landscape, strange creature] colors: [gold, blue, brown] 隐式语义标注: - 维度: 象征 解读: 软化的时钟象征时间的相对性表现潜意识中对时间流逝的焦虑。 依据: 画面中的时钟以柔软变形的方式呈现与达利超现实主义创作理念相关。 置信度: 0.92具体的生成内容会因模型能力、温度参数和知识库内容不同而有所差异。5.3 人工审核与反馈闭环标注结果生成后ArtAnno 的界面应支持人工审核。审核结果写回 FeedbackMemory形成闭环# 文件路径api/review.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import Dict, List from artanno.agent.memory.feedback_memory import FeedbackMemory app FastAPI() memory FeedbackMemory() class ReviewRequest(BaseModel): image_id: str metadata: Dict[str, str] implicit_semantics: List[Dict] accepted: bool app.post(/review) def submit_review(req: ReviewRequest): 提交人工审核结果 if req.accepted: memory.save_feedback({ image_id: req.image_id, metadata: req.metadata, implicit_semantics: req.implicit_semantics, status: accepted }) return {status: ok, message: 标注已保存为参考样本} else: # 可以记录修改后的标注 return {status: ok, message: 标注已被驳回等待修改}“增强”在这里体现得非常直接每次人工确认都在为系统积累更高质量的先验知识后续 Agent 在生成新标注时会自动参考这些样本。6. 常见问题与排查思路基于 ArtAnno 的实现过程这里整理几个实际开发中常见的问题。问题现象常见原因解决思路视觉描述返回空结果图像编码失败或模型不支持图像输入检查 Base64 编码、确认模型类型、控制图像大小LLM 返回的不是合法 JSON模型输出不稳定使用response_format、Function Calling 或增加解析兜底逻辑知识检索结果为空知识库为空或向量索引未构建检查文档是否加入、向量维度是否匹配隐式语义解读过度提示词中缺少约束条件在 Prompt 中加入“仅依据画面与提供的知识不要主观臆断”反馈记忆不生效首次使用没有历史样本预置一批高质量标注作为冷启动数据标注耗时过长多模块串行调用 LLM视觉描述与知识检索可并行采用异步调用具体排查时可以遵循以下顺序确认 API Key 和模型名是否正确。先单独测试视觉描述模块确认图像能正常解析。再测试知识检索模块确认向量索引没有异常。最后测试 Agent 编排逻辑逐段打日志定位问题。如果生成结果质量差优先调整提示词而不是换模型。7. 最佳实践与工程建议7.1 提示词设计的艺术ArtAnno 的效果高度依赖提示词质量。建议从三个维度设计提示词角色约束明确告诉模型它是“艺术史学者”还是“文化研究助手”这会显著影响输出风格。证据约束要求模型在输出标注时附带“依据”既能降低幻觉也便于人工审核。输出格式约束尽量统一 JSON Schema减少下游解析成本。7.2 人机协同的边界管理不是所有标注都适合 LLM 自动完成。对于置信度较低的标注系统应该主动标记为“需人工审阅”而不是强行输出。可以在流程中加入一个置信度阈值判断def filter_low_confidence(semantics, threshold0.6): return [item for item in semantics if item.get(confidence, 0) threshold]这样可以保证进入知识库的标注质量减少对人工的干扰。7.3 知识库的持续运营隐式语义标注的准确性很大程度上依赖知识库的丰富程度。建议定期补充权威艺术史文献。标注通过人工审核后反哺知识库形成正向循环。不同用户的审美偏好可能不同标注结果应保留多版本而不是只保留最主流解读。注意作品版权与数据合规图像和解读内容的使用范围需要明确。7.4 成本与性能优化LLM 调用成本在批量标注场景下不可忽视。可以从几个角度降低成本视觉描述和知识检索使用轻量模型隐式语义推断使用强模型。对同一幅画重复标注时缓存视觉描述结果。批量任务改造为异步队列避免高并发打爆 API 配额。对相似画作复用标注结果减少重复推理。8. 后续扩展方向与学习路线ArtAnno 项目展示了 LLM Agent 在垂直领域的一个典型应用范式但它的扩展空间还很大。如果你打算继续深入这个方向可以按下面的路线来学习第一阶段掌握 LLM Agent 基础学习 LangChain 或自研 Agent 框架掌握 ReAct 模式、工具调用、多轮对话管理。第二阶段多模态理解实践了解 GPT-4V、Qwen-VL 等视觉语言模型的使用方式熟悉图像编码和视觉描述生成这对艺术图像理解非常重要。第三阶段知识增强与检索学习向量数据库、RAG检索增强生成技术掌握知识注入和上下文管理。艺术史知识具有较强的图结构特性也可以尝试知识图谱方案。第四阶段人机协同产品落地理解标注工具设计、置信度评估、主动学习等概念。ArtAnno 的核心价值不只是一个标注模型而是一套可持续迭代的人机协同系统。第五阶段数据飞轮与质量评估建立隐式语义标注的评估指标比如与人工标注的一致性、专家评审通过率、标注间的可解释性。这类指标决定了系统能否真正进入生产环境。如果你对 LLM Agent 编排、RAG 知识检索、多模态应用开发感兴趣ArtAnno 是一个小而完整的研究载体可以帮你把零散的技术点串成一条完整的应用链路。从最简单的视觉描述开始逐步加入知识检索、Agent 推理、人工反馈闭环就能构建一个真正能用的语义标注系统。