统一消息层
在 Neuron AI 中,Message(消息)是与大语言模型(LLM)交互的统一上下文单元。不同 AI 提供商(如 OpenAI、Anthropic、Gemini)的 API 请求格式差异巨大,Neuron AI 通过统一的 Message 对象屏蔽了这些底层差异,让你只需编写一次代码即可无缝切换不同的 LLM 提供商。
Message 结构
一条标准的 Message 对象由以下三个核心部分组成:
- Role(角色):标识消息的来源,通常是
user(用户)或 assistant(助手)。 - Content Blocks(内容块):消息的实际载荷。一条消息可以包含一个或多个内容块(例如:一段文本 + 一张图片)。
- Metadata(元数据):可选的附加信息,例如 LLM 响应中的 Token 使用量等。
核心消息类型
Neuron AI 提供了两个主要的类来表示对话中的双方:
1. UserMessage(用户消息)
代表用户的输入,作为 Agent 的 chat() 方法的参数传入。
2. AssistantMessage(助手消息)
代表大模型生成的回复,作为 chat()->getMessage() 的返回值。
基础纯文本用法:
当你直接传入字符串时,框架会自动将其转换为包含一个 TextContent 块的 UserMessage。
useNeuronAI\Chat\Messages\UserMessage;// 构造一个简单的文本消息$message = new UserMessage("你好,请介绍一下开源技术小栈。");// 传入 Agent 执行$response = MyAgent::make()->chat($message)->getMessage(); // $response 是一个 AssistantMessage 对象
多模态内容块
为了支持图片、文件、音频和视频等输入,Neuron AI 引入了 ContentBlock 的概念。以下是官方支持的内置内容块类型:
| | |
|---|
TextContent | | |
ImageContent | | |
FileContent | | |
AudioContent | | |
VideoContent | | |
ReasoningContent | | |
多模态数据的来源类型
对于非文本内容(图片、文件等),Neuron AI 支持三种数据来源(SourceType):
SourceType::URL:通过公网 URL 引用资源。(最简单,无需本地读取)SourceType::BASE64:将本地文件编码为 Base64 字符串传输。SourceType::ID:使用提供商平台已上传文件的 ID。(最省钱,避免每次请求都重复传输大文件消耗 Token)
完整使用案例
下面演示如何在实际业务中构建各种类型的多模态消息。
这里使用智普多模态 GLM-5V-Turbo 模型。
GLM-5V-Turbo 是智谱首个多模态 Coding 基座模型,面向视觉编程任务打造。能够原生处理图片、视频、文本等多模态输入,同时擅长长程规划、复杂编程和动作执行;深度适配 Agent 工作流,能够与 Claude Code、OpenClaw 等 Agent 深度协同,完成”看懂环境→规划动作→执行任务”的完整闭环。
文档:https://docs.bigmodel.cn/cn/guide/models/vlm/glm-5v-turbo
案例 1:发送包含图片的消息(URL 方式)
假设你的应用需要让大模型分析一张网络上的图片:
多模态Agent ZAITurboAgent
<?php/** * @desc ZAIImageAgent.php 描述信息 * @author Tinywan(ShaoBo Wan) * @link 模型概览 https://docs.bigmodel.cn/cn/guide/start/model-overview */declare(strict_types=1);namespace app\neuron\agent;use NeuronAI\Agent\Agent;use NeuronAI\Providers\AIProviderInterface;use NeuronAI\Providers\ZAI\ZAI;classZAITurboAgentextendsAgent{publicfunctionprovider(): AIProviderInterface{returnnew ZAI( key: getenv('ZAI_KEY'), model: 'glm-5v-turbo', ); }publicfunctioninstructions(): string{return'你是是智谱首个多模态 Coding 基座模型,面向视觉编程任务打造'; }}
多模态调用
<?php/** * @desc TinywanAgent * @author Tinywan(ShaoBo Wan) */declare(strict_types=1);namespace app\controller;use app\neuron\agent\ZAITurboAgent;use NeuronAI\Chat\Enums\SourceType;use NeuronAI\Chat\Messages\ContentBlocks\ImageContent;use NeuronAI\Chat\Messages\UserMessage;use support\Request;classIndexController{publicfunctionimage(Request $request): ?string{// 1. 图片地址 $imageUrl = 'https://www.tinywan.com/assets/c008d6e8-0dab-421c-b8f1-c482891f045d-BDTJKrAD.png';// 2. 创建 UserMessage $message = new UserMessage('请帮我分析这张图片的内容');// 3. 添加图片内容块(ZAI API 只接受 base64 格式) $message->addContent(new ImageContent( content: $imageUrl, sourceType: SourceType::URL, mediaType: 'image/png' ) );// 4. 发送给 Agent $agent = ZAITurboAgent::make() ->chat($message) ->getMessage();return $agent->getContent(); }}
案例 2:发送本地 PDF 文件(Base64 方式)
假设用户上传了一个 PDF 发票,你需要让大模型提取信息:
useNeuronAI\Chat\Messages\UserMessage;use NeuronAI\Chat\Messages\ContentBlocks\FileContent;use NeuronAI\Chat\Messages\ContentBlocks\SourceType;$filePath = '/var/www/uploads/invoice.pdf';$message = new UserMessage("请提取这张发票上的金额和日期。");$message->addContent(new FileContent(// 将本地文件读取并转为 Base64 编码 source: base64_encode(file_get_contents($filePath)), sourceType: SourceType::BASE64, mediaType: 'application/pdf' ));$response = MyAgent::make()->chat($message)->getMessage();
案例 3:组合多条文本与图片
一条消息可以包含任意数量的内容块:
$message = new UserMessage("这里有两组设计图,请对比它们的差异。");$message->addContent(new TextContent("第一组设计图:"));$message->addContent(new ImageContent('https://example.com/design1.jpg', SourceType::URL, 'image/jpeg'));$message->addContent(new TextContent("第二组设计图:"));$message->addContent(new ImageContent('https://example.com/design2.jpg', SourceType::URL, 'image/jpeg'));
如何读取大模型的返回内容
大模型返回的内容(AssistantMessage)可能包含纯文本,也可能包含推理链或其他内容。Neuron AI 提供了不同的方法来读取这些内容:
1. getContent() —— 获取纯文本(最常用)
如果你只关心最终的文字回答,直接使用此方法。它会将消息中所有的 TextContent 块拼接成一个字符串返回。
$response = MyAgent::make()->chat(new UserMessage("讲个笑话"))->getMessage();echo $response->getContent(); // 输出: 为什么程序员不喜欢户外?因为有太多的 bug!
2. getContentBlocks() —— 获取所有内容块(高级用法)
如果大模型返回了推理过程(如 OpenAI o1 模型),或者你想处理多模态输出,需要遍历内容块数组。
useNeuronAI\Chat\Messages\ContentBlocks\TextContent;useNeuronAI\Chat\Messages\ContentBlocks\ReasoningContent;$response = MyAgent::make()->chat(new UserMessage("证明勾股定理"))->getMessage();foreach ($response->getContentBlocks() as $block) {if ($block instanceof ReasoningContent) {echo"[大模型的思考过程]: " . $block->content . "\n"; } elseif ($block instanceof TextContent) {echo"[最终回复]: " . $block->content . "\n"; }}
3. getTextBlocks() —— 仅获取文本块数组
如果你明确知道返回内容中只有文本,但希望以数组形式处理,可以使用此方法。
$textBlocks = $response->getTextBlocks();foreach ($textBlocks as $block) {echo $block->content . "\n";}
总结与最佳实践
- 统一接口:无论底层是 OpenAI 还是 Anthropic,你的代码只需操作
UserMessage 和 AssistantMessage,这就是 Neuron AI 提供的核心价值。 - 生产环境高频处理大文件:先调用提供商的上传 API 获取 ID,然后使用
ID,可大幅降低 Token 消耗和延迟。
- 多模态支持验证:在发送
ImageContent 或 FileContent 之前,请确保你在 provider() 中配置的模型(如 gpt-4o 或 claude-3-5-sonnet)支持对应的多模态输入能力。