
之前在不少“AI 学习机”类产品上看到过这样的功能演示对着桌子上的苹果拍一张照片平板里的人工智能助手不仅能告诉你“这是一个红苹果”还会用苹果的第一人称开口说话“你好呀我是红富士苹果削皮吃更甜哦……”第一眼觉得很神奇但拆开看背后的技术链路其实并不复杂摄像头采集图片 → 视觉模型完成物体识别 → 大语言模型基于识别结果做角色扮演 → 语音合成播报。核心就两件事拍照识别和提示词设计。这篇文章会从零讲解如何自己动手做一个“拍照识别万物 万物开口说话”的自定义智能体包含完整代码、提示词模板、可视化平台搭建思路和常见排错方案。无论你是 AI 产品经理、全栈开发者还是准备做教育类应用的学生团队都可以照着实现一版原型。1. 背景与核心概念1.1 智能体Agent到底是什么“智能体”这个词近两年频繁出现但很多读者对它仍然比较模糊。简单理解智能体就是一个能自主完成多步骤任务的 AI 程序。它不再只是“你问一句、它答一句”的聊天机器人而是可以这样工作的能力说明例子理解任务解析用户的自然语言请求“帮我看看桌上是什么水果”调用工具调用摄像头、图片识别接口、搜索、计算器读取图片文件并传给视觉模型规划步骤拆解任务并决定先做什么、后做什么先识别物体再生成拟人介绍使用记忆记住上下文支持多轮对话用户追问物体产地时能接上话题输出结果以文字、语音、卡片等形式回复用合成语音把介绍读出来“自定义智能体”则是在通用智能体能力之上允许开发者或用户自己配置提示词、知识库、工具和工作流。你不需要从零训练模型只需要把已有的模型能力组合起来定义好行为规则。1.2 拍照识别万物的实现路径传统的“拍照识物”依赖图像分类模型模型能回答“这是什么”但遇到没见过的物体就很难处理。现在的视觉大模型VLMVision-Language Model直接把“看图说话”变成了一件很自然的事输入一张图片模型能理解图像内容结合自然语言指令输出识别结果、属性描述、背景知识。实现链路一般为摄像头/相册取图 → 图片编码 → 调用视觉模型接口 → 获得文字描述 → 进入对话智能体 → 语音播报也就是说识别能力由视觉模型负责开口说话的能力由语言模型负责。如果你使用的模型本身自带视觉理解能力这两个步骤甚至可以合并成一次调用。1.3 “万物开口说话”的本质是提示词角色扮演让物体“开口说话”不是真的给物体装了嘴巴而是通过**提示词Prompt**让大语言模型以物体的第一人称视角进行表达。这个思路可以拆成三层识别层确定图片中的核心物体角色层让模型扮演该物体表达层用规定的语气、格式、篇幅输出自我介绍。核心技巧是系统提示词。只要提示词设计得当同一个模型既能做严肃的百科讲解也能立刻变成一只“会说话的保温杯”。1.4 整体架构认知先建立一幅完整的架构图后续所有代码都围绕它展开用户打开应用 → 拍摄/上传图片 → 应用把图片发送给视觉模型 → 得到物体名称和属性 → 拼入“万物说话”系统提示词 → 调用大模型生成拟人介绍 → 合成语音播放 → 支持多轮追问如果你选择集成 Dify、Coze 这类智能体平台整个流程可以拖拽完成不需要写太多代码如果选择自研则需要自己串联各个 API。下文两种方案都会覆盖。2. 环境准备与基础选型2.1 软硬件准备本文示例以 Python 3.9 为主你只需要一台能联网的电脑即可运行核心代码。如果要在手机或学习机上落地还需要准备Android / iOS 设备或带摄像头的开发板一个可用的视觉模型 API一个可用的语音合成TTSAPI智能体编排平台账号可选用于可视化搭建。操作系统方面Windows、macOS、Linux 均可。本文演示以命令行为主不依赖特定 IDE。2.2 模型选型建议目前市面上有多款支持图片输入的视觉语言模型常见的包括通义千问 VL 系列、GLM-4V、GPT-4o、Claude 等多模态版本。不同模型的接口调用方式略有差异但很多国产模型都提供了 OpenAI 兼容的接口格式因此代码可以复用。选择模型时建议关注三点识别准确度对常见物体、文字、场景的理解能力中文表达质量拟人化自我介绍是否自然接口成本和延迟学习机/教学场景通常需要低成本、低延迟。需要说明的是具体型号和价格变化较快请以各平台官方文档为准。本文的代码示例思路可以通用实际使用时替换为你的模型服务地址即可。2.3 智能体平台选型如果你不想从零写代码市面上已经有成熟的智能体搭建平台例如 Dify。这类平台的核心价值是可视化编排大模型工作流支持上传知识库让回答更贴合业务内置工具调用和对话管理方便接入微信公众号、Web、API 等渠道。自研方案则适合需要深度定制、数据不出内网、或产品形态比较特殊的团队。方案优点缺点适合场景智能体平台上手快、迭代快、无需维护基础设施灵活性受平台限制快速验证需求、教育产品原型自研调用 API完全可控、可定制需要自己处理并发、安全、日志企业应用、定制硬件、私有化部署2.4 项目结构设计自研方案建议采用如下项目结构便于后续扩展photo_agent/ ├── main.py # 主入口 ├── agent.py # 智能体逻辑封装 ├── vision.py # 图片识别工具 ├── prompts.py # 提示词模板 ├── config.py # 配置管理 ├── requirements.txt # 依赖清单 └── images/ # 存放测试图片3. 核心原理拆解3.1 视觉识别链路调用视觉模型的基本流程是一致的读取图片本地图片以二进制方式读取Base64 编码把图片二进制转为字符串便于在 JSON 请求中传输构造消息消息中包含图片数据和文本指令发送请求调用大模型接口解析结果从返回内容中提取文本描述。有一个重要的工程细节图片体积。手机照片动辄几 MB直接传给模型会导致请求慢、费用高。建议上传前做压缩处理一般将长边缩放到 1024 像素以内JPEG 质量控制在 85 左右能明显提升响应速度且识别效果损失很小。3.2 提示词工程基础提示词是指导大模型行为的“说明书”。一个高质量的提示词通常包含以下部分角色设定让模型扮演什么角色任务描述需要完成什么任务输入信息用户提供的数据或上文结果输出格式规定输出结构如 JSON、限定字数限制条件哪些不能说、哪些必须说示例Few-shot给一两个范例让模型模仿。在“万物开口说话”场景中角色设定是核心。你希望模型扮演的是“图片里的那个物体”而不是一个见过这个物体的解说员。3.3 让物体开口说话的关键提示词结构直接给模型发一张图片它通常会给出客观描述“图片中是一个白色保温杯杯身上有卡通图案。”如果想让保温杯“开口说话”提示词要改写为你看到图片后请判断图片中最主要的物体。 然后请你以这个物体的身份用第一人称“我”来介绍自己。 不要使用“图片中的这个物体”这种第三人称表达。关键语法点在于人称切换。大模型对“你扮演谁”的理解非常敏感只要在系统提示词里明确“你是图片里的那个物体”输出内容就会完全不同。按照这个思路我们可以设计一个更完整的系统提示词模板后面实战部分会给出可直接复制的版本。3.4 对话上下文与记忆“万物开口说话”不能只播报一次就结束用户可能会追问“你是什么做的”“你适合用来做什么”“能讲个关于你的小故事吗”为了让追问有连贯性需要把历史消息一并传给模型。大多数大模型接口都支持多轮消息结构你只需要维护一个messages数组每轮对话后追加用户消息和助手回复。对于简单原型直接把历史消息拼到请求里即可数据量大时建议引入数据库或向量记忆。4. 完整实战案例搭建一个会“开口说话”的拍照识别智能体下面进入代码实战。示例中我以 OpenAI 兼容接口为例来演示请根据你实际使用的模型服务替换base_url和model参数。4.1 创建项目结构在命令行执行mkdir photo_agent cd photo_agent touch main.py agent.py vision.py prompts.py config.py requirements.txt mkdir images创建虚拟环境并安装依赖python -m venv venv source venv/bin/activate # Windows 使用 venv\Scripts\activate pip install openai # 如果你还需要图片压缩可以安装 Pillow pip install pillowrequirements.txt内容如下openai1.0.0 pillow10.0.04.2 配置管理为了避免把密钥写死在代码里我们使用config.py统一管理配置# 文件路径photo_agent/config.py import os # 从环境变量读取避免密钥泄露 API_KEY os.getenv(VLM_API_KEY, ) BASE_URL os.getenv(VLM_BASE_URL, https://your-model-service.example.com/v1) MODEL os.getenv(VLM_MODEL, your-vision-model) TTS_API_KEY os.getenv(TTS_API_KEY, ) TTS_MODEL os.getenv(TTS_MODEL, your-tts-model)如果你的模型服务不需要 OpenAI 兼容方式请按官方文档调整客户端调用方式。4.3 编写图片预处理与识别函数视觉模型通常支持两种图片传递方式一种是传图片 URL另一种是传 Base64 编码后的图片内容。本地图片使用 Base64 更简单。# 文件路径photo_agent/vision.py import base64 import io from PIL import Image def compress_image(image_path: str, max_side: int 1024, quality: int 85) - str: 压缩图片并返回 Base64 字符串。 :param image_path: 本地图片路径 :param max_side: 图片最长边像素 :param quality: JPEG 压缩质量 with Image.open(image_path) as img: # 转换为 RGB避免 PNG 透明通道带来的问题 img img.convert(RGB) # 等比缩放 width, height img.size if width height and width max_side: new_width max_side new_height int(height * max_side / width) img img.resize((new_width, new_height)) elif height max_side: new_height max_side new_width int(width * max_side / height) img img.resize((new_width, new_height)) # 压缩并编码 buffer io.BytesIO() img.save(buffer, formatJPEG, qualityquality) encoded base64.b64encode(buffer.getvalue()).decode(utf-8) return encoded注意不同模型对图片大小、格式有不同限制如果遇到“图片过大”的错误可以进一步降低max_side和quality。4.4 设计“万物说话”系统提示词这是整个项目的灵魂。下面的提示词模板可以直接复制使用也可以根据你的产品风格调整。# 文件路径photo_agent/prompts.py OBJECT_SPEAKER_PROMPT 你是一台智能拍照讲解助手具备看图说话和角色扮演能力。 任务流程 1. 用户会发送一张图片。 2. 请你识别图片中最核心、最醒目的物体。 3. 然后你不再是一个旁观者而是变成图片中的那个物体。 4. 以这个物体的第一人称“我”的身份向用户进行自我介绍。 自我介绍必须包含 - 我是什么名称、类别 - 我的主要用途 - 我有什么有趣的特点或冷知识 - 关于我的一个实用小提示 表达要求 - 全程使用中文。 - 语气亲切、自然、有童趣像一位耐心的朋友。 - 必须使用第一人称“我”不要用“图片中的这个物体”这类第三人称描述。 - 字数控制在 150 到 250 字之间。 - 如果用户继续提问请继续保持物体身份回答直到用户明确要求你回到讲解员身份。 - 如果图片中没有任何明确物体请如实说明不要编造。 SYSTEM_DEFAULT_PROMPT 你是一台智能拍照讲解助手。 当用户发送图片时你负责识别并介绍图片中的物体。 如果用户没有发送图片你可以回答关于拍照识物、智能体使用等一般性问题。看到区别了吗OBJECT_SPEAKER_PROMPT强制模型做角色扮演SYSTEM_DEFAULT_PROMPT则是普通助手。实际产品中可以根据开关切换两套提示词。4.5 组装智能体核心逻辑接下来把视觉识别和对话逻辑封装成一个类。# 文件路径photo_agent/agent.py import json from openai import OpenAI from prompts import OBJECT_SPEAKER_PROMPT, SYSTEM_DEFAULT_PROMPT from vision import compress_image class PhotoAgent: def __init__(self, api_key: str, base_url: str, model: str): self.client OpenAI(api_keyapi_key, base_urlbase_url) self.model model self.history [] def _reset_system_prompt(self, enable_object_speaker: bool True): 重建消息历史设置系统提示词。 system_prompt OBJECT_SPEAKER_PROMPT if enable_object_speaker else SYSTEM_DEFAULT_PROMPT self.history [{role: system, content: system_prompt}] def chat_with_image(self, image_path: str, user_text: str 你好请介绍一下你自己, enable_object_speaker: bool True): 发送图片并让智能体回复。 :param image_path: 本地图片路径 :param user_text: 用户想要对物体说的话 :param enable_object_speaker: 是否开启“万物开口说话”角色扮演模式 if not self.history or self.history[0][role] ! system: self._reset_system_prompt(enable_object_speaker) base64_image compress_image(image_path) # 把系统提示词与本次图片请求放在一起 user_content [ { type: image_url, image_url: {url: fdata:image/jpeg;base64,{base64_image}}, }, { type: text, text: user_text, }, ] # 追加本轮用户消息 self.history.append({role: user, content: user_content}) response self.client.chat.completions.create( modelself.model, messagesself.history, temperature0.7, ) answer response.choices[0].message.content # 追加助手回复到历史支持后续追问 self.history.append({role: assistant, content: answer}) return answer def clear_history(self): self.history []这段代码的核心价值在于维护了多轮对话历史。第一次提问时图片和文本一起发给模型之后用户追问时不再重复发图片模型也能依据历史中的图片描述继续回答。4.6 编写主入口# 文件路径photo_agent/main.py import config from agent import PhotoAgent def main(): agent PhotoAgent( api_keyconfig.API_KEY, base_urlconfig.BASE_URL, modelconfig.MODEL, ) image_path images/cup.jpg print( 已开启万物开口说话模式输入 q 退出) while True: user_text input(你想对它说) if user_text.lower() q: break # 首轮对话附带图片后续追问不带图片 if not agent.history: answer agent.chat_with_image(image_path, user_text, enable_object_speakerTrue) else: answer agent.chat_without_image(user_text) print(\n回答\n, answer, \n) if __name__ __main__: main()为了让chat_without_image可用需要在agent.py中补充一个纯文本对话方法def chat_without_image(self, user_text: str): 不附带图片的对话用于追问场景。 self.history.append({role: user, content: user_text}) response self.client.chat.completions.create( modelself.model, messagesself.history, temperature0.7, ) answer response.choices[0].message.content self.history.append({role: assistant, content: answer}) return answer4.7 运行与验证准备一张测试图片例如images/cup.jpg然后执行export VLM_API_KEY你的密钥 export VLM_BASE_URL你的模型服务地址 export VLM_MODEL你的视觉模型名称 python main.py预期输出效果类似于 已开启万物开口说话模式输入 q 退出 你想对它说你好请介绍一下你自己 回答 大家好呀我是一个白色陶瓷马克杯平时主要用来装咖啡、热茶和牛奶。 我的杯身圆润厚实保温效果还不错冬天捧着暖暖的。 悄悄告诉你刚倒进热水时先别急着喝放凉到 60 度左右口感更合适。 希望以后每天都能陪你度过惬意的喝饮时光如果没有得到第一人称回答而是出现“图片中是一个马克杯”这类描述说明系统提示词没有被正确加载请检查history数组中第一条消息是否为OBJECT_SPEAKER_PROMPT。4.8 接入语音合成要让“万物开口说话”真正变成“开口说”还需要语音合成。主流云服务商都提供 TTS 接口核心思路是把智能体生成的文字转成音频播放。简化版流程# 伪代码示例请按你的 TTS 服务文档调整 import requests def text_to_speech(text: str, output_path: str): url https://your-tts-service.example.com/v1/audio/speech headers {Authorization: fBearer {config.TTS_API_KEY}} payload { model: config.TTS_MODEL, input: text, voice: cute_boy, # 按服务商提供的音色选择 } response requests.post(url, jsonpayload, headersheaders) with open(output_path, wb) as f: f.write(response.content) return output_path注意不同 TTS 服务的请求字段差异很大请以官方文档为准。如果是在移动端落地也可以把 TTS 能力集成在客户端减少服务器压力。5. 基于 Dify 等智能体平台的可视化搭建对于非开发者或需要快速验证产品的团队直接使用智能体平台会更高效。以 Dify 这类可视化平台为例搭建思路如下。5.1 应用类型选择平台上通常提供两类应用聊天助手Chatbot适合多轮对话用户可追问工作流Workflow适合一次性任务比如“图片输入 → 输出介绍”。“万物开口说话”建议选择聊天助手因为用户会追问。如果做批量识别则选择工作流。5.2 配置模型与工具在应用配置页中选择支持视觉输入的模型并确认模型已开启图片理解能力开启图片上传功能让用户能在对话中发送图片如需要语音播报增加一个“文本转语音”工具节点。这里的核心配置项是模型选择如果模型不支持图片输入后面的所有设计都无法生效。5.3 编写系统提示词把 4.4 节中的OBJECT_SPEAKER_PROMPT原样粘贴到平台系统提示词区域即可。不同平台对图片消息的传递方式不同但大体思路一致用户在对话窗口上传图片后模型会把图片作为上下文上下文的一部分接收。如果平台支持“变量”可以把“识别结果”设为中间变量方便后续节点引用{{#sys.query#}} 是用户输入 {{#sys.image#}} 是用户上传的图片这样后面节点可以基于识别结果生成语音、保存记录或推送通知。5.4 发布到服务渠道配置完成后平台通常提供以下发布方式Web 应用生成一个聊天页面链接API 服务以 HTTP 接口方式供自己的应用调用第三方渠道接入公众号、钉钉、飞书、企业微信等。建议先通过 Web 页面验证效果确认识别和角色扮演稳定后再开放 API 给小程序或学习机客户端。5.5 平台方式与自研方式如何选择如果目标是快速做出 Demo直接选平台方式通常一小时内就能上线一个可用的“拍照识物万物说话”智能体。如果目标是把能力嵌入自己的 App需要深度定制界面、控制数据流转建议用自研方式把核心逻辑做成独立的 Agent 服务。6. 常见问题与排查思路在开发和调试过程中比较容易遇到以下几类问题。这里整理成表格方便按图索骥问题现象常见原因解决思路模型返回“无法理解图片内容”模型不支持图像输入或图片编码错误更换支持视觉输入的模型检查 Base64 是否正确、有无 data URL 前缀识别结果不准确图片模糊、光线差、画面中物体过多换清晰的单物体图片测试压缩时不要过度降低质量物体“开口说话”变成了第三人称客观描述系统提示词没有生效或消息 history 未正确设置检查第一条 system 消息确认是否用了角色扮演提示词模板用户追问后模型忘记图片内容多轮对话时没有携带历史消息在请求中携带完整 messages 数组而不仅是当前问题响应速度很慢或费用高图片未压缩体积过大使用 Pillow 压缩到长边 1024、质量 85合理控制并发输出内容包含幻觉信息模型对物体不确定时编造知识在提示词中明确“不确定就说不确定”为知识类回答引入知识库上传图片被服务拒绝格式不支持常见为 HEIC、WebP服务端统一转为 JPEG 后再调用模型语音播报听起来像念稿TTS 音色选择不当或没有去除 Markdown 符号给 TTS 前先清理特殊字符尝试多种音色6.1 关于判断问题现象以“第三人称回答”为例很多读者第一次运行后会发现模型回复是图片中是一个保温杯杯身是白色的……这就是典型的角色扮演失败。排查顺序建议如下确认系统提示词是否包含“你是图片中的那个物体”“使用第一人称我”字样确认请求结构中system消息位于第一条尝试更换模型部分模型对复杂角色扮演的遵循能力较弱在提示词中加入一段示例例如“例如看到一只猫就说‘我是小猫咪喜欢在窗台晒太阳’。”多数情况下加入示例后问题即可解决。7. 最佳实践与工程建议7.1 提示词版本管理提示词是 AI 应用的“核心代码”建议用 Git 管理提示词文件。每次调整系统提示词后都要记录变更原因和测试效果方便回滚。你可以把提示词按场景拆分成独立文件例如object_speaker.txt、knowledge_tutor.txt运行时动态选择。7.2 让输出更稳定结构化输出如果后续需要把识别结果用于业务逻辑建议要求模型返回 JSON 结构例如请按以下 JSON 格式返回 { object_name: 物体名称, description: 一句话概括, speech: 第一人称自我介绍 }结构化输出方便程序解析也方便做后续的数据统计和质量评估。7.3 视觉输入环节的工程优化在拍照识物场景中图片质量直接决定效果。建议在客户端做这些预检对焦提示引导用户让物体处于画面中心光线提示光线不足时提醒开灯或靠近窗户单物体优先提示“请拍一个物体”避免画面杂乱上传前压缩降低延迟和成本。7.4 内容安全与合规如果是面向学习机、儿童教育场景必须考虑内容安全。建议做到三点模型输出前增加敏感词过滤和内容审核接口系统提示词中明确“不要回答与物体无关的不安全内容”在应用层面限制未成年人的持续聊天时长并保留日志用于审计。另外不要使用任何声称“无限制”“无审核”的模型服务。正规教育产品需要的是可信、可控、可追溯的内容生成能力。7.5 性能与成本控制视觉模型的调用成本通常高于纯文本模型。可以考虑以下策略先做一次轻量分类识别出物体类别后再决定是否需要调用更强的大模型对同一物体的重复提问做缓存减少模型调用次数开启异步处理让语音播报和模型生成并行执行减少用户等待时间。7.6 评估与迭代上线后的迭代依赖数据建议记录以下指标用户平均提问轮数角色扮演成功率人工抽检识别准确率与标注对比语音播报完整率平均响应时间。每两周抽一批用户会话进行质量评估把失败案例补充到提示词的“注意”部分模型表现会越来越稳定。8. 总结与延伸方向通过本文你应该已经掌握了实现“拍照识别万物 万物开口说话”的核心方法视觉模型负责把图片变成文字知识系统提示词负责让模型以物体第一人称进行表达多轮消息结构负责支持用户追问语音合成负责把文字变成声音智能体平台可以帮你把上述流程可视化、产品化。比较大的坑有两个一是模型必须真正支持图片输入否则后面所有步骤都无法进行二是角色扮演是否自然完全取决于系统提示词的质量值得花时间反复打磨。如果你想把项目做得更深可以继续探索以下方向知识库增强给智能体挂载一个植物、动物、生活用品知识库让介绍内容更准确、更丰富多物体识别一次识别图中多个物体并允许用户选择让哪个物体“开口说话”个性化音色结合 TTS 让不同类别物体配备不同音色例如动物用童声、电器用沉稳声离线端侧部署在嵌入式设备上部署轻量化视觉模型和语音合成模型实现完全离线。这套能力不止能做学习机。家庭教育、博物馆导览、盲人辅助、商品营销展示都可以直接复用。从一个“会说话的马克杯”开始你完全可以构建出属于自己的智能体产品。动手改一版提示词拍一张身边的物品体验一下 AI 从“看”到“说”的完整链路吧。