FEATURED · 精选文章

拍照识别万物+万物开口说话:多模态大模型与提示词工程实战

发布时间 / 2026/9/7 9:57:01
来源 / 创域科博编辑部
栏目 / 资讯中心
拍照识别万物+万物开口说话:多模态大模型与提示词工程实战 先说结论这类“拍照识别万物 万物开口说话”的小智 AI 学习机本质上就是把多模态大模型、提示词工程和语音合成三件事串成一条自动化链路。思路并不复杂很多开发者卡在“不知道怎么设计提示词”和“不知道怎么把拍照、识别、说话串起来”这两步。本文会把完整链路拆开讲清楚并给出平台版和代码版两套可落地方案。像我之前自己做儿童 AI 学习助手原型时最先想做的功能也是“拿摄像头对着动物、植物、玩具拍一张然后 AI 用这个物体的口吻跟孩子说话”。当时以为难点在识别后来才发现识别反而最好解决真正花时间的是提示词设计和多轮对话的状态管理。这篇文章就把整套经验整理出来包含提示词模板、后端代码、前端页面和排查清单适合想自己做 AI 学习机、智能体应用或拍照识物小工具的开发者参考。1. 背景与核心概念1.1 一个需求拆成三个功能点标题里的需求看起来很长但拆开之后其实是三个独立功能功能技术本质关键词拍照识别万物多模态视觉模型识别图片内容拍照识别、视觉大模型AI 聊天学习大语言模型多轮对话智能体、AI 对话万物开口说话提示词工程 语音合成提示词、TTS、角色扮演这里有一个很容易踩的坑很多人把“万物开口说话”理解成需要额外的语音克隆或者拟人音色库。实际上只要你让 AI 先识别出“这是什么”再把自己的身份设定成“这个东西”然后用第一人称说话就已经实现了“万物开口”。整个过程不需要新的模型只需要改提示词。1.2 拍照识别走的是多模态大模型所谓“多模态”简单说就是模型既能理解文字也能理解图片、音频等非文字信息。你把一张照片传给这类模型它会输出对图片内容的文字描述或者直接回答你关于图片的问题。常见做法是选用支持图片输入的视觉语言模型比如通义千问 VL、智谱 GLM-4V、OpenAI GPT-4o、豆包视觉理解等。无论选哪个基本流程都是一样的上传图片 → 视觉模型解析图片内容 → 生成结构化描述 → 交给对话模型处理1.3 “万物开口说话”本质是提示词切换“模拟万物开口说话”并不是让模型真的模拟声音而是通过系统提示词System Prompt告诉模型你现在是什么角色。你用什么人称说话。你说话的语气和风格。你面对的用户是谁。你的知识边界是什么。同一样的识别结果系统提示词不同AI 说出来的话就完全不同。这就是提示词工程的威力。例如同样识别出“一只猫”普通模式“这是一只猫属于猫科动物……”猫的口吻“喵我是小猫咪我喜欢吃小鱼干你看我的胡须可以测量缝隙……”老师的口吻“小朋友这是猫。猫是一种常见的宠物它的特点是……”所以自定义智能体的第一课就是学会控制和设计系统提示词。2. 技术选型与执行思路2.1 平台型方案低代码快速验证如果你不想从零搭建后端推荐先使用智能体开发平台做原型验证。常见的平台有 Dify、Coze 扣子、百度千帆等它们一般已经内置了多模态模型接入、知识库、插件和工作流编排能力。平台方案的好处是快从零到可以演示基本只需要半天。适合验证产品需求。新手学习智能体开发。不想维护服务器的个人开发者。平台方案的缺点也比较明显上线后按调用量计费成本不可控。提示词和流程被绑定在平台上迁移困难。多模态识别和语音合成的定制化能力有限。所以如果只是做学习项目平台方案足够如果要真正部署成学习机或智能硬件建议走代码方案。2.2 代码型方案灵活可控代码型方案的整体架构推荐这样做前端页面/App → 后端服务 → 多模态模型 → 文本结果 → TTS 语音合成 → 音频返回 ↘ 对话上下文存储 ↗以 Python 技术栈为例后端可以用 FastAPI 搭建 HTTP 服务前端用一个简单的 H5 页面调用摄像头拍照再把图片传给后端。依赖项大致包括FastAPI提供上传接口和音频接口。多模态模型 SDK 或 HTTP 接口。文本转语音 TTS 服务。简单的内存缓存或 Redis用于保存多轮对话状态。2.3 整体流程设计用户点击拍照 → 图片上传到后端 → 后端调用视觉模型识别 → 结合自定义提示词生成回复文本 → 调 TTS 生成音频 → 前端播放音频为了让“万物开口说话”的效果更好可以设计一个两阶段提示词先用“识别提示词”让模型输出图片内容的标准化描述。再用“角色提示词”让模型以识别出的物体身份说话。这样可以避免角色设定干扰识别准确度也方便二次开发。3. 环境准备与项目结构3.1 运行环境说明本文以 Python 3.10 以上版本为例操作系统使用 Windows 或 Ubuntu 均可只要环境变量配置正确。具体版本不需要严格固定根据你实际安装的版本调整即可。需要提前准备好的工具Python 3.10Node.js可选前端简单页面可以直接用浏览器打开不需要构建可用的视觉大模型 API Key可用的 TTS 服务3.2 项目目录结构建议把代码按照下面的结构组织后面扩展也比较方便ai_learning_machine/ ├── main.py # FastAPI 入口 ├── config.py # 配置文件 ├── requirements.txt # Python 依赖 ├── prompts.py # 提示词模板 ├── services/ │ ├── vision_service.py # 图片识别服务 │ └── tts_service.py # 语音合成服务 ├── static/ │ ├── index.html # 拍照页面 │ └── camera.js # 摄像头调用逻辑 └── uploads/ # 临时存放上传的图片接下来逐步创建这些文件。4. 核心代码与提示词实现这一节按照核心模块讲解最后一个章节会给出完整的整合示例。4.1 拍照上传接口前端通过摄像头拍照后会把图片以 Base64 字符串或二进制文件的形式传给后端。推荐用二进制文件上传传输效率更高后端也好处理。# 文件路径main.py片段 from fastapi import FastAPI, File, UploadFile import os import uuid app FastAPI() UPLOAD_DIR uploads os.makedirs(UPLOAD_DIR, exist_okTrue) app.post(/upload) async def upload_image(file: UploadFile File(...)): # 生成唯一文件名避免冲突 ext file.filename.split(.)[-1] if . in file.filename else jpg filename f{uuid.uuid4().hex}.{ext} file_path os.path.join(UPLOAD_DIR, filename) # 保存图片到本地 content await file.read() with open(file_path, wb) as f: f.write(content) return {code: 0, message: success, file_path: file_path}这里需要注意UploadFile 是 FastAPI 对上传文件对象的封装await file.read() 可以异步读取整个文件内容。对于学习项目图片通常不会很大直接读入内存没有问题生产环境建议限制文件大小避免内存被打满。4.2 多模态识别逻辑以 OpenAI 兼容接口为例视觉模型调用方式如下# 文件路径services/vision_service.py示例思路 import base64 import os from openai import OpenAI client OpenAI( api_keyos.getenv(VISION_API_KEY), base_urlos.getenv(VISION_BASE_URL, https://api.openai.com/v1) ) def encode_image_to_base64(file_path: str) - str: with open(file_path, rb) as image_file: return base64.b64encode(image_file.read()).decode(utf-8) def recognize_image(file_path: str) - str: base64_image encode_image_to_base64(file_path) response client.chat.completions.create( modelos.getenv(VISION_MODEL, gpt-4o-mini), messages[ { role: user, content: [ {type: text, text: 请描述这张图片里的主体物体是什么尽量简洁只告诉我物体名称和主要特征。}, {type: image_url, image_url: {url: fdata:image/jpeg;base64,{base64_image}}} ] } ] ) return response.choices[0].message.content注意不同平台的模型名称和 Base URL 不同实际使用时以你所选平台的官方文档为准。上面的代码是 OpenAI 兼容格式很多国产模型的兼容接口也支持这种格式可以直接替换 Base URL 和模型名。识别提示词这里建议写得明确一点让模型只输出识别结果不要输出大段百科内容。这样后续“开口说话”时模型不会因为混杂了识别阶段的解释而显得啰嗦。4.3 万物开口说话的提示词设计这是本文最核心的部分。先看一个效果对比。同样识别出“一棵树”直接问模型“这是什么”回答通常很客观这是一棵树属于植物界是木本植物……但如果你在后面接上这样一条系统提示词你现在是一棵树请用第一人称介绍自己像一个可爱的朋友一样跟小朋友说话语气活泼语句简短。模型就会变成这样嗨我是一棵大树我的头发是绿色的叶子夏天的时候可以给你挡太阳哦核心提示词模板可以这样设计# 文件路径prompts.py DEFAULT_CHARACTER_PROMPT 你是一个{role_name}。 请用第一人称“我”来介绍你自己。 你正在和一位{user_name}说话请用{language}回答。 你的语气{style}。 你的回答要简短自然控制在 3 到 5 句话以内。 不要直接说“我是由AI生成的”之类的话。 .strip() RECOGNITION_PROMPT 请识别这张图片中最主要的物体或场景输出结果格式为 实体名称{名称} 实体类别{物体/动物/植物/场景/其他} 主要特征{20字以内的描述} 不要输出其他内容。 .strip()实际生成最终提示词时可以这样拼接def build_character_prompt(entity_name: str, user_name: str 小朋友) - str: return DEFAULT_CHARACTER_PROMPT.format( role_nameentity_name, user_nameuser_name, language中文, style活泼、亲切、像朋友一样 )需要说明的是角色提示词并不一定非要单独调用一次模型。如果你用的是支持系统提示词的平台可以直接把识别结果填进系统提示词然后让模型一句话完成“识别 扮演”两个任务。两阶段方案更适合代码模式因为可以单独评测识别准度和扮演效果。4.4 语音合成最后一步是把 AI 生成的文本转成语音让设备“开口说话”。TTS 也有多种选择云端 TTS阿里云、腾讯云、微软 Azure 等。开源 TTSEdge-TTS免费适合学习、CosyVoice、ChatTTS 等。一些多模态平台也自带语音生成接口。以 Edge-TTS 为例代码非常简单# 文件路径services/tts_service.py import edge_tts import os VOICE zh-CN-XiaoxiaoNeural async def text_to_speech(text: str, output_path: str) - str: communicate edge_tts.Communicate(text, VOICE) await communicate.save(output_path) return output_pathEdge-TTS 的优点是免费、不需要 Key适合本地学习验证。但它的网络请求依赖微软服务生产环境建议替换为商业 TTS 以保证 SLA。5. 完整可运行示例这一节把上面的模块整合起来形成一个可以直接运行的最小闭环。5.1 后端整合代码# 文件路径main.py完整版 import os import uuid from fastapi import FastAPI, File, UploadFile from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from prompts import build_character_prompt, RECOGNITION_PROMPT from services.vision_service import recognize_image from services.tts_service import text_to_speech app FastAPI() UPLOAD_DIR uploads AUDIO_DIR audio os.makedirs(UPLOAD_DIR, exist_okTrue) os.makedirs(AUDIO_DIR, exist_okTrue) app.mount(/static, StaticFiles(directorystatic), namestatic) app.post(/api/recognize) async def recognize_and_speak(file: UploadFile File(...)): try: # 1. 保存图片 ext file.filename.split(.)[-1] if . in file.filename else jpg image_path os.path.join(UPLOAD_DIR, f{uuid.uuid4().hex}.{ext}) content await file.read() with open(image_path, wb) as f: f.write(content) # 2. 识别图片 entity recognize_image(image_path) # 3. 生成角色提示词 character_prompt build_character_prompt(entity_nameentity, user_name小朋友) # 4. 为了演示这里直接使用识别文本作为回答实际项目中可以再次调用对话模型 answer_text f我{entity}今天很高兴见到你 # 5. 合成语音 audio_path os.path.join(AUDIO_DIR, f{uuid.uuid4().hex}.mp3) await text_to_speech(answer_text, audio_path) return { code: 0, entity: entity, answer_text: answer_text, audio_url: f/audio/{os.path.basename(audio_path)} } except Exception as e: return {code: 1, message: str(e)} app.get(/audio/{filename}) async def get_audio(filename: str): file_path os.path.join(AUDIO_DIR, filename) if not os.path.exists(file_path): return {code: 1, message: audio not found} return FileResponse(file_path, media_typeaudio/mpeg)注意上面第 4 步中为了演示直接拼接了识别结果。实际项目中应该把识别结果作为上下文再次调用对话模型生成“万物开口说话”的内容这样才会真的像在聊天。5.2 前端摄像头页面前端页面很朴素核心是调用getUserMedia获取摄像头画面然后通过 Canvas 截图并上传。!-- 文件路径static/index.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title小智拍照识别 - 万物开口说话/title /head body h2 拍照识别万物/h2 video idvideo width480 height360 autoplay playsinline/video brbr button idtakePhoto拍照识别/button button idswitchCamera切换摄像头/button h3识别结果/h3 div idresult/div audio idaudioPlayer controls styledisplay:none;/audio script let currentStream null; let usingFrontCamera true; async function initCamera() { if (currentStream) { currentStream.getTracks().forEach(track track.stop()); } const constraints { video: { facingMode: usingFrontCamera ? environment : user } }; currentStream await navigator.mediaDevices.getUserMedia(constraints); const video document.getElementById(video); video.srcObject currentStream; } async function takePhoto() { const video document.getElementById(video); const canvas document.createElement(canvas); canvas.width video.videoWidth; canvas.height video.videoHeight; const context canvas.getContext(2d); context.drawImage(video, 0, 0, canvas.width, canvas.height); const blob await new Promise(resolve canvas.toBlob(resolve, image/jpeg, 0.9)); const formData new FormData(); formData.append(file, blob, photo.jpg); const resultDiv document.getElementById(result); resultDiv.innerHTML 识别中…; const response await fetch(/api/recognize, { method: POST, body: formData }); const data await response.json(); if (data.code 0) { resultDiv.innerHTML p识别实体${data.entity}/p pAI 回答${data.answer_text}/p ; const audio document.getElementById(audioPlayer); audio.src data.audio_url; audio.style.display block; audio.play(); } else { resultDiv.innerHTML 识别失败${data.message}; } } document.getElementById(takePhoto).addEventListener(click, takePhoto); document.getElementById(switchCamera).addEventListener(click, async () { usingFrontCamera !usingFrontCamera; await initCamera(); }); initCamera().catch(err { document.getElementById(result).innerHTML 摄像头调用失败${err.message}; }); /script /body /html这个页面里facingMode: environment代表使用后置摄像头适合拍摄物体user代表前置摄像头适合自拍或对话。切换摄像头时需要先停掉当前所有轨道否则会同时占用摄像头导致黑屏。5.3 运行与验证首先安装依赖pip install fastapi uvicorn python-multipart edge-tts openai然后启动服务uvicorn main:app --reload --host 0.0.0.0 --port 8000浏览器访问http://localhost:8000/static/index.html预期效果页面弹出摄像头权限请求允许后可以看到实时画面。点击“拍照识别”页面把图片发送到后端。后端返回识别实体、回答文本和音频地址。浏览器自动播放音频AI 用设定角色开口说话。如果是在手机上访问需要把localhost换成电脑的局域网 IP并且电脑和手机处于同一 Wi-Fi。6. 提示词优化与效果调试6.1 识别准确度优化多模态模型对清晰度非常敏感。如果经常识别错误优先检查拍摄距离是否合适物体是否过小。光线是否充足是否有严重反光。是否多个物体同时入镜主体不明确。图片是否压缩过于严重。可以在识别提示词里增加“如果图片中有多个物体请优先识别中心位置的物体”这样的约束效果会有提升。6.2 开口说话的自然度优化如果 AI 说话像背稿子通常是提示词太“死”。可以加入一些社交化、口语化的要求你正在和一位 6 岁小朋友聊天。 请使用短句多用语气词比如“呀”“哦”“好不好呀”。 不要一次性输出超过 50 个字。 适当使用拟声词。另外可以让模型在回复前先把识别结果隐藏起来不要直接说“我是一棵树”而是从打招呼开始再慢慢引入自己是谁这样更自然。6.3 语气与情感控制同一个角色可以配置多种语气模板由上层逻辑决定切换到哪种。比如教学模式语气耐心解释原理。故事模式语气夸张富有戏剧性。闲聊模式语气轻松简短互动。这种“性格切换”就是智能体常说的“人格设定”本质上还是提示词管理。建议把语气模板单独放在一个配置文件里而不是写死在业务代码中。6.4 多轮对话设计如果只是单次识别不需要上下文。但智能体通常需要连续对话比如先问“你是什么”再问“你住在哪里”。这时候需要保存历史消息。最简单的做法是在内存中维护一个 session_id 到消息列表的映射# 示例思路 session_messages {} def append_message(session_id: str, role: str, content: str): if session_id not in session_messages: session_messages[session_id] [] session_messages[session_id].append({role: role, content: content}) # 限制长度避免上下文过长 session_messages[session_id] session_messages[session_id][-10:]生产环境建议用 Redis 保存会话并设置过期时间。对话轮数多了之后要给上下文做截断或摘要否则模型输入越来越长成本和延迟都会上升。7. 常见问题与排查思路7.1 常见报错与解决方案问题现象常见原因解决思路摄像头黑屏未授权摄像头权限或前置/后置切换时未停掉旧流检查浏览器权限设置切换前先 stop 所有 track上传图片后一直转圈后端未启动或手机访问了错误地址检查 uvicorn 日志确认端口和局域网 IP识别结果错误图片主体不清晰、识别提示词约束不足扩大识别主体占比增加“识别中心物体”提示AI 回答像百科复制角色提示词没有生效确认系统提示词在请求中是否被正确传递TTS 语音没有播放音频 URL 不可访问或媒体类型错误检查 /audio 接口返回值确认 media_type 是否设置正确内存占用过高上传图片过大或未做文件大小限制后端限制文件大小前端压缩后再上传7.2 排查清单如果功能没跑通可以按下面顺序排查前端是否能调用摄像头浏览器是否弹出权限提示接口 /api/recognize 是否收到请求返回是否包含 code0图片是否保存成功uploads 目录下有没有文件视觉模型是否返回内容查看后端日志。音频文件是否生成成功audio 目录下有没有 mp3浏览器能否直接访问 audio_url在地址栏手动打开试试。如果是局域网访问检查系统防火墙是否放行了 8000 端口。7.3 避免问题再次出现所有外部 API 调用都要做异常捕获避免一个接口失败拖垮整个链路。在识别之前用 OpenCV 或 Pillow 对图片做预处理比如统一缩放、旋转校正。TTS 生成的音频要缓存同一个文本不要重复合成节省成本。开发时把敏感配置放环境变量不要把 API Key 写进代码。8. 安全边界与工程建议8.1 数据与隐私拍照识物会涉及图像数据上传。学习项目可以忽略但做生产应用时必须考虑传输过程使用 HTTPS避免图片被中间人窃取。图片如果只用于识别建议识别后立即删除不持久化保存。如果有儿童用户需要遵循相关合规要求尽量做到最小化采集。明确告知用户拍照数据的使用目的和保留期限。8.2 接口安全后端 /api/recognize 接口不能完全无鉴权地暴露公网。最低限度也应该做简单的 Token 校验。上传频率限制防止接口被刷。文件类型白名单检查不能只依赖文件后缀。限制单次上传文件大小比如 10MB。8.3 成本控制这类智能体应用的成本大头在模型调用和 TTS 合成。建议对识别结果做缓存同一个物体短时间内不要重复识别。使用低成本小模型做前置过滤再用大模型做精细回答。TTS 结果按文本哈希缓存到磁盘重复文本直接复用音频。对话上下文不过长保存避免每次请求的输入 token 持续膨胀。8.4 生产环境建议代码型方案真正部署时建议把架构升级为Nginx → FastAPI 集群 → 消息队列 → 模型服务池也可以把视觉识别和语音合成拆成独立微服务通过队列异步处理。学习阶段不必这么做但要清楚模块之间的解耦边界否则后面改需求时会比较痛苦。另外模型服务建议通过统一网关封装方便切换供应商也能在模型故障时快速降级。这一点在依赖大模型 API 的应用里尤其重要。9. 总结与下一步方向到这里一条完整的“拍照识别万物 万物开口说话”链路已经讲完了。回顾一下核心点有四个拍照识物的底层是多模态视觉模型不要在传统图像分类上死磕。万物开口说话的本质是提示词切换识别和扮演最好分成两个阶段。语音合成选择可以根据成本灵活调整免费方案适合学习商业方案适合上线。多轮对话需要独立管理上下文不能依赖单次识别接口顺手完成。如果要把这个项目做成真正可用的 AI 学习机下一步建议优先做三件事把“识别→扮演”改成完整的两次大模型调用让角色说话内容更丰富。加入多轮对话管理让 AI 能记住用户名字和偏好。引入知识库让 AI 在扮演万物时还能穿插正确的科普知识避免一本正经地胡说八道。拍照识物只是智能体的一个入口提示词工程才是决定体验上限的关键。在你真正动手改提示词、跑通第一个对话之前看再多教程都只是“知道”跑通一次之后你自然就理解智能体开发的核心套路了。这篇文章完整版代码结构在前文已经给出如果你在跑的过程中卡在某一步大概率问题出在依赖版本或网络访问上优先看控制台日志一般都是信息量最大的线索。动手试一下吧等你的“万物开口说话”跑通的那一刻成就感确实不一样。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻