HarmonyOS 6(API 23)多智能体协作编排 × 分布式软总线——构建“一呼百应“的跨设备智能体集群

每日一句正能量
度,是恰到好处的分寸,是过犹不及的警醒。
“度”是做事、说话、待人接物中的黄金分割点。它提醒我们,凡事超过了限度就和不及一样糟糕。儒家讲“中庸”,道家讲“知止”,核心都是这个“度”。它需要情境智慧,没有固定公式,只能靠觉察调整。
一、前言:从"单兵作战"到"集群协作"的智能体进化
在第一百零八篇中,我们实现了单个HMAF智能体与悬浮导航、沉浸光感的融合。但在真实的企业级场景中,单一智能体往往难以应对复杂任务——比如"帮我策划一场从北京到三亚的5天家庭旅行",这涉及机票查询、酒店预订、景点推荐、行程规划、预算核算等多个专业领域,需要多个垂域智能体协同完成。
HarmonyOS 6(API 23)在HMAF 2.0基础上,正式开放了多智能体协作框架(Multi-Agent Collaboration Framework,简称MACF),结合鸿蒙独有的**分布式软总线(Distributed Soft Bus)**能力,实现了跨设备智能体的发现、调度、通信与协作。
本文核心亮点:我们将实战构建一个"旅行智能体集群",包含机票Agent、酒店Agent、景点Agent、预算Agent四个专业智能体。它们分布在手机、平板、PC三台设备上,通过分布式软总线自动发现彼此,由"旅行管家Agent"作为协调者进行任务拆解与结果聚合,最终通过沉浸光感的UI呈现完整行程方案。
二、技术架构总览
2.1 多智能体协作架构
┌─────────────────────────────────────────────────────────────────────────────┐
│ 协调层(Coordinator) │
│ ┌─────────────────────────────────────┐ │
│ │ 旅行管家Agent(TravelMaster) │ │
│ │ - 意图拆解 - 任务分配 - 结果聚合 │ │
│ └─────────────────┬───────────────────┘ │
│ │ │
├──────────────────────────────────────┼──────────────────────────────────────┤
│ 分布式软总线(Distributed Soft Bus) │
│ 设备发现 │ 服务注册 │ 跨设备RPC │ 数据总线 │ │
│ (DeviceDiscovery) (ServiceRegistry) (CrossDeviceRPC) (DataBus) │
│ │ │
├──────────────────┬───────────────────┼───────────────────┬──────────────────┤
│ 手机设备 │ 平板设备 │ PC设备 │ 手表设备 │
│ ┌──────────────┐ │ ┌──────────────┐ │ ┌──────────────┐ │ │
│ │ 机票Agent │ │ │ 酒店Agent │ │ │ 景点Agent │ │ │
│ │ - 航班查询 │ │ │ - 酒店搜索 │ │ │ - 景点推荐 │ │ │
│ │ - 价格比较 │ │ │ - 房态确认 │ │ │ - 路线规划 │ │ │
│ │ - 预订下单 │ │ │ - 优惠计算 │ │ │ - 门票预订 │ │ │
│ └──────────────┘ │ └──────────────┘ │ └──────────────┘ │ │
│ ┌──────────────┐ │ │ ┌──────────────┐ │ │
│ │ 预算Agent │ │ │ │ 沉浸光感UI │ │ │
│ │ - 费用汇总 │ │ │ │ - 行程看板 │ │ │
│ │ - 预算预警 │ │ │ │ - 情绪渲染 │ │ │
│ │ - 支付建议 │ │ │ │ - 动态光效 │ │ │
│ └──────────────┘ │ │ └──────────────┘ │ │
│ 悬浮导航入口 │ │ 大屏展示中心 │ │
└──────────────────┴────────────────────┴───────────────────┴─────────────────┘
2.2 关键技术栈
| 技术模块 | API/框架 | 作用 |
|---|---|---|
| MACF | @ohos/macf |
多智能体协作框架,负责任务编排 |
| 分布式软总线 | @ohos.distributedHardware |
跨设备发现、连接、通信 |
| 分布式对象 | @ohos.distributedObject |
跨设备状态同步 |
| HMAF Skill | @ohos/hmaf |
单智能体能力封装 |
| 沉浸光感 | @ohos/immersive-light |
协作状态可视化 |
| 悬浮导航 | windowManager.createWindow |
跨设备统一入口 |
三、核心代码实战
3.1 项目配置与依赖
// oh-package.json5
{
"name": "multi-agent-travel",
"version": "1.0.0",
"description": "HarmonyOS 6 多智能体协作 × 分布式软总线 × 沉浸光感实战",
"dependencies": {
"@ohos/hmaf": "2.0.0",
"@ohos/macf": "1.0.0",
"@ohos/distributed-hardware": "5.0.0",
"@ohos/distributed-object": "5.0.0",
"@ohos/immersive-light": "1.2.0",
"@ohos/float-window": "1.1.0"
}
}
// module.json5 权限声明
{
"module": {
"requestPermissions": [
{ "name": "ohos.permission.DISTRIBUTED_DATASYNC" },
{ "name": "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER" },
{ "name": "ohos.permission.GET_WIFI_INFO" },
{ "name": "ohos.permission.GET_NETWORK_INFO" },
{ "name": "ohos.permission.SYSTEM_FLOAT_WINDOW" },
{ "name": "ohos.permission.INTERNET" }
]
}
}
3.2 分布式软总线:设备发现与服务注册
代码亮点:实现了基于分布式软总线的智能体自动发现机制。当旅行管家Agent启动时,它会自动扫描局域网内的鸿蒙设备,发现其他专业Agent并建立P2P连接。
// src/distributed/DeviceDiscoveryManager.ts
import { distributedDeviceManager } from '@kit.DistributedServiceKit';
import { distributedHardware } from '@kit.DistributedHardwareKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
/**
* 分布式设备发现管理器
* 核心功能:
* 1. 自动发现局域网内鸿蒙设备
* 2. 智能体服务注册与发现
* 3. 设备能力协商与连接管理
*/
export class DeviceDiscoveryManager {
private deviceManager: distributedDeviceManager.DeviceManager;
private registeredAgents: Map<string, AgentEndpoint> = new Map();
private onDeviceFoundCallback?: (devices: DiscoveredDevice[]) => void;
private onAgentDiscoveredCallback?: (agent: DiscoveredAgent) => void;
constructor() {
this.deviceManager = distributedDeviceManager.createDeviceManager('com.example.travel');
}
/**
* 启动设备发现
*/
async startDiscovery(): Promise<void> {
// 订阅设备上线/下线事件
this.deviceManager.on('deviceStateChange', (data) => {
hilog.info(0x0000, 'Discovery', `Device state changed: ${JSON.stringify(data)}`);
this.handleDeviceStateChange(data);
});
// 启动主动发现
const filterOptions: distributedDeviceManager.SubscribeInfo = {
subscribeId: 10001,
mode: distributedDeviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE,
medium: distributedDeviceManager.ExchangeMedium.AUTO,
freq: distributedDeviceManager.ExchangeFreq.HIGH,
isSameAccount: false,
capability: distributedDeviceManager.SubscribeCap.SUBSCRIBE_CAP_OSD
};
await this.deviceManager.startDeviceDiscovery(filterOptions);
hilog.info(0x0000, 'Discovery', 'Device discovery started');
}
/**
* 注册本机智能体服务
*/
async registerAgentService(agentInfo: AgentInfo): Promise<void> {
const serviceId = `agent://${agentInfo.type}/${agentInfo.id}`;
// 通过分布式软总线注册服务
await distributedHardware.registerService({
serviceId: serviceId,
serviceType: 'agent',
capabilities: agentInfo.capabilities,
properties: {
agentType: agentInfo.type,
agentName: agentInfo.name,
version: agentInfo.version,
deviceType: deviceInfo.deviceType // phone/tablet/pc
}
});
this.registeredAgents.set(serviceId, {
serviceId,
agentInfo,
status: AgentStatus.AVAILABLE
});
hilog.info(0x0000, 'Discovery', `Agent registered: ${serviceId}`);
}
/**
* 发现远程智能体
*/
async discoverRemoteAgents(): Promise<DiscoveredAgent[]> {
const agents: DiscoveredAgent[] = [];
// 获取已连接设备列表
const devices = this.deviceManager.getAvailableDeviceListSync();
for (const device of devices) {
// 向每个设备查询其注册的智能体服务
try {
const remoteAgents = await this.queryRemoteAgents(device.networkId);
agents.push(...remoteAgents.map(agent => ({
...agent,
deviceId: device.deviceId,
deviceName: device.deviceName,
deviceType: device.deviceType
})));
} catch (err) {
hilog.warn(0x0000, 'Discovery', `Failed to query device ${device.deviceName}: ${err}`);
}
}
return agents;
}
/**
* 查询远程设备上的智能体(跨设备RPC)
*/
private async queryRemoteAgents(networkId: string): Promise<AgentEndpoint[]> {
// 使用分布式软总线的RPC能力
const proxy = distributedHardware.createRpcProxy(networkId, 'agent_registry');
const response = await proxy.call('listAgents', {});
return response.agents || [];
}
/**
* 建立与远程Agent的通信通道
*/
async connectToAgent(agentId: string): Promise<AgentConnection> {
const agent = Array.from(this.registeredAgents.values()).find(a => a.agentInfo.id === agentId);
if (!agent) {
throw new Error(`Agent ${agentId} not found`);
}
// 创建跨设备数据通道
const dataBus = await distributedHardware.createDataBus({
targetDevice: agent.agentInfo.deviceId,
channelType: ' reliable', // 可靠传输
qos: { bandwidth: 1024 * 1024 } // 1MB/s
});
return new AgentConnection(agent, dataBus);
}
private handleDeviceStateChange(data: distributedDeviceManager.DeviceStateChangeInfo): void {
if (data.state === distributedDeviceManager.DeviceStateChangeAction.ONLINE) {
// 新设备上线,触发智能体发现
this.discoverRemoteAgents().then(agents => {
agents.forEach(agent => this.onAgentDiscoveredCallback?.(agent));
});
}
}
setOnDeviceFound(callback: (devices: DiscoveredDevice[]) => void): void {
this.onDeviceFoundCallback = callback;
}
setOnAgentDiscovered(callback: (agent: DiscoveredAgent) => void): void {
this.onAgentDiscoveredCallback = callback;
}
}
interface AgentInfo {
id: string;
type: string; // 'flight' | 'hotel' | 'attraction' | 'budget'
name: string;
version: string;
capabilities: string[];
}
interface AgentEndpoint {
serviceId: string;
agentInfo: AgentInfo;
status: AgentStatus;
}
enum AgentStatus {
AVAILABLE = 'available',
BUSY = 'busy',
OFFLINE = 'offline'
}
interface DiscoveredDevice {
deviceId: string;
deviceName: string;
deviceType: string;
networkId: string;
}
interface DiscoveredAgent extends AgentEndpoint {
deviceId: string;
deviceName: string;
deviceType: string;
}
class AgentConnection {
constructor(
public endpoint: AgentEndpoint,
private dataBus: distributedHardware.DataBus
) {}
async invoke(method: string, params: any): Promise<any> {
const request = { method, params, timestamp: Date.now() };
const response = await this.dataBus.sendAndReceive(request);
return response.data;
}
async close(): Promise<void> {
await this.dataBus.close();
}
}
3.3 多智能体协作编排器:旅行管家的"指挥中枢"
代码亮点:实现了基于**合同网协议(Contract Net Protocol)**的多智能体任务分配机制。旅行管家Agent将复杂任务拆解为子任务,向所有可用Agent广播招标,各Agent根据自身能力投标,最终由管家选择最优组合执行。
// src/agents/TravelMasterOrchestrator.ts
import { DeviceDiscoveryManager, AgentConnection, DiscoveredAgent } from '../distributed/DeviceDiscoveryManager';
import { LightEffectManager } from '../effects/LightEffectManager';
import { hilog } from '@kit.PerformanceAnalysisKit';
/**
* 旅行管家编排器
* 核心能力:
* 1. 复杂意图拆解(旅行规划 → 机票+酒店+景点+预算)
* 2. 基于合同网协议的任务分配
* 3. 并行执行与结果聚合
* 4. 冲突检测与协商(如酒店位置与景点距离冲突)
* 5. 沉浸光感状态可视化
*/
export class TravelMasterOrchestrator {
private discoveryManager: DeviceDiscoveryManager;
private availableAgents: Map<string, DiscoveredAgent> = new Map();
private agentConnections: Map<string, AgentConnection> = new Map();
private lightEffect: LightEffectManager;
// 任务执行状态
@State private executionState: ExecutionState = ExecutionState.IDLE;
constructor() {
this.discoveryManager = new DeviceDiscoveryManager();
this.lightEffect = LightEffectManager.getInstance();
// 监听智能体发现事件
this.discoveryManager.setOnAgentDiscovered((agent) => {
this.availableAgents.set(agent.agentInfo.id, agent);
hilog.info(0x0000, 'Orchestrator', `Agent discovered: ${agent.agentInfo.name} on ${agent.deviceName}`);
});
}
/**
* 初始化:启动发现并注册本机服务
*/
async initialize(): Promise<void> {
await this.discoveryManager.startDiscovery();
await this.discoveryManager.registerAgentService({
id: `travel-master-${deviceInfo.deviceId}`,
type: 'travel-master',
name: '旅行管家',
version: '1.0.0',
capabilities: ['intent_parsing', 'task_decomposition', 'result_aggregation', 'conflict_resolution']
});
}
/**
* 核心方法:处理旅行规划请求
*/
async planTrip(userRequest: string): Promise<TripPlan> {
this.executionState = ExecutionState.PLANNING;
this.lightEffect.render('thinking', 0.8); // 思考中光效
// Step 1: 意图拆解
const tripIntent = await this.parseTravelIntent(userRequest);
hilog.info(0x0000, 'Orchestrator', `Intent parsed: ${JSON.stringify(tripIntent)}`);
// Step 2: 任务分解
const subTasks = this.decomposeTasks(tripIntent);
hilog.info(0x0000, 'Orchestrator', `Decomposed into ${subTasks.length} sub-tasks`);
// Step 3: 智能体招标(合同网协议)
const assignments = await this.contractNetAllocation(subTasks);
hilog.info(0x0000, 'Orchestrator', `Task assignments: ${JSON.stringify(assignments)}`);
// Step 4: 并行执行
this.executionState = ExecutionState.EXECUTING;
this.lightEffect.render('excited', 0.9); // 执行中光效
const results = await this.executeInParallel(assignments);
// Step 5: 冲突检测与协商
this.executionState = ExecutionState.NEGOTIATING;
const resolved = await this.resolveConflicts(results);
// Step 6: 结果聚合与行程生成
this.executionState = ExecutionState.AGGREGATING;
const tripPlan = await this.aggregateTripPlan(resolved, tripIntent);
// Step 7: 完成光效
this.executionState = ExecutionState.COMPLETED;
this.lightEffect.render('warm', 0.7);
return tripPlan;
}
/**
* 意图拆解:将自然语言转为结构化旅行需求
*/
private async parseTravelIntent(request: string): Promise<TravelIntent> {
// 使用端侧NLU模型
const nluResult = await aiEngine.nluParse(request, {
domain: 'travel_planning',
entities: ['destination', 'origin', 'dates', 'travelers', 'budget', 'preferences']
});
return {
origin: nluResult.entities.origin || '北京',
destination: nluResult.entities.destination,
departureDate: nluResult.entities.dates?.start,
returnDate: nluResult.entities.dates?.end,
travelers: parseInt(nluResult.entities.travelers) || 2,
budget: nluResult.entities.budget,
preferences: nluResult.entities.preferences || [],
rawRequest: request
};
}
/**
* 任务分解
*/
private decomposeTasks(intent: TravelIntent): SubTask[] {
const tasks: SubTask[] = [];
// 任务1:机票查询
tasks.push({
id: 'task-flight',
type: 'flight_search',
description: `查询${intent.origin}到${intent.destination}的往返机票`,
parameters: {
origin: intent.origin,
destination: intent.destination,
departureDate: intent.departureDate,
returnDate: intent.returnDate,
travelers: intent.travelers,
budget: intent.budget ? intent.budget * 0.4 : undefined // 预算的40%用于机票
},
requiredCapabilities: ['flight_search', 'price_compare'],
priority: 1 // 最高优先级
});
// 任务2:酒店搜索
tasks.push({
id: 'task-hotel',
type: 'hotel_search',
description: `搜索${intent.destination}的酒店`,
parameters: {
city: intent.destination,
checkIn: intent.departureDate,
checkOut: intent.returnDate,
guests: intent.travelers,
budget: intent.budget ? intent.budget * 0.35 : undefined, // 35%用于酒店
preferences: intent.preferences.filter(p => ['海景', '市中心', '亲子'].includes(p))
},
requiredCapabilities: ['hotel_search', 'room_availability'],
priority: 2
});
// 任务3:景点推荐
tasks.push({
id: 'task-attraction',
type: 'attraction_recommend',
description: `推荐${intent.destination}的景点和路线`,
parameters: {
city: intent.destination,
days: this.calculateDays(intent.departureDate, intent.returnDate),
preferences: intent.preferences.filter(p => ['文化', '自然', '美食', '购物'].includes(p)),
travelers: intent.travelers
},
requiredCapabilities: ['attraction_recommend', 'route_plan'],
priority: 3
});
// 任务4:预算核算
tasks.push({
id: 'task-budget',
type: 'budget_calculation',
description: '汇总费用并检查预算',
parameters: {
totalBudget: intent.budget,
expectedExpenses: ['flight', 'hotel', 'attraction', 'food', 'transport']
},
requiredCapabilities: ['budget_calc', 'price_forecast'],
priority: 4,
dependsOn: ['task-flight', 'task-hotel', 'task-attraction'] // 依赖前三项结果
});
return tasks;
}
/**
* 合同网协议:任务分配
*/
private async contractNetAllocation(tasks: SubTask[]): Promise<TaskAssignment[]> {
const assignments: TaskAssignment[] = [];
for (const task of tasks) {
// 1. 广播招标(Call for Proposals)
const proposals: AgentProposal[] = [];
for (const [agentId, agent] of this.availableAgents) {
// 检查Agent是否具备所需能力
const hasCapabilities = task.requiredCapabilities.every(
cap => agent.agentInfo.capabilities.includes(cap)
);
if (!hasCapabilities) continue;
try {
const connection = await this.getOrCreateConnection(agentId);
// 发送CFP,获取投标
const proposal = await connection.invoke('bid', {
taskId: task.id,
taskType: task.type,
parameters: task.parameters
});
proposals.push({
agentId,
agentName: agent.agentInfo.name,
deviceName: agent.deviceName,
estimatedCost: proposal.estimatedCost,
estimatedTime: proposal.estimatedTime,
confidence: proposal.confidence,
proposalData: proposal
});
} catch (err) {
hilog.warn(0x0000, 'Orchestrator', `Agent ${agentId} failed to bid: ${err}`);
}
}
if (proposals.length === 0) {
throw new Error(`No agent available for task: ${task.id}`);
}
// 2. 评估投标并选择最优(多目标优化:成本、时间、置信度)
const bestProposal = this.selectBestProposal(proposals, task);
assignments.push({
task,
assignedAgent: bestProposal,
status: 'assigned'
});
hilog.info(0x0000, 'Orchestrator',
`Task ${task.id} assigned to ${bestProposal.agentName} on ${bestProposal.deviceName}`);
}
return assignments;
}
/**
* 选择最优投标(加权评分)
*/
private selectBestProposal(proposals: AgentProposal[], task: SubTask): AgentProposal {
// 评分权重:成本30% + 时间30% + 置信度40%
const weights = { cost: 0.3, time: 0.3, confidence: 0.4 };
const scored = proposals.map(p => {
// 归一化评分(越高越好)
const minCost = Math.min(...proposals.map(x => x.estimatedCost));
const maxCost = Math.max(...proposals.map(x => x.estimatedCost));
const costScore = maxCost === minCost ? 1 : (maxCost - p.estimatedCost) / (maxCost - minCost);
const minTime = Math.min(...proposals.map(x => x.estimatedTime));
const maxTime = Math.max(...proposals.map(x => x.estimatedTime));
const timeScore = maxTime === minTime ? 1 : (maxTime - p.estimatedTime) / (maxTime - minTime);
const totalScore =
costScore * weights.cost +
timeScore * weights.time +
p.confidence * weights.confidence;
return { ...p, score: totalScore };
});
scored.sort((a, b) => b.score - a.score);
return scored[0];
}
/**
* 并行执行所有任务
*/
private async executeInParallel(assignments: TaskAssignment[]): Promise<Map<string, TaskResult>> {
const promises = assignments.map(async (assignment) => {
const connection = await this.getOrCreateConnection(assignment.assignedAgent.agentId);
// 发送执行任务请求
const result = await connection.invoke('execute', {
taskId: assignment.task.id,
parameters: assignment.task.parameters
});
return {
taskId: assignment.task.id,
result
};
});
const results = await Promise.all(promises);
const resultMap = new Map<string, TaskResult>();
results.forEach(r => resultMap.set(r.taskId, r.result));
return resultMap;
}
/**
* 冲突检测与协商
*/
private async resolveConflicts(results: Map<string, TaskResult>): Promise<Map<string, TaskResult>> {
const resolved = new Map(results);
// 检测1:酒店位置与景点距离冲突
const hotelResult = resolved.get('task-hotel');
const attractionResult = resolved.get('task-attraction');
if (hotelResult && attractionResult) {
const hotelLocation = hotelResult.data.location;
const dailyRoutes = attractionResult.data.dailyRoutes;
// 检查每天的第一站与酒店距离
for (const day of dailyRoutes) {
const firstAttraction = day.attractions[0];
const distance = this.calculateDistance(hotelLocation, firstAttraction.location);
if (distance > 30) { // 超过30km视为冲突
hilog.warn(0x0000, 'Orchestrator',
`Conflict detected: Hotel is ${distance}km from first attraction on day ${day.day}`);
// 触发协商:重新搜索更近的酒店或调整景点顺序
const negotiated = await this.negotiateHotelAdjustment(hotelResult, day);
resolved.set('task-hotel', negotiated);
}
}
}
// 检测2:预算超支
const budgetResult = resolved.get('task-budget');
if (budgetResult && budgetResult.data.overBudget) {
hilog.warn(0x0000, 'Orchestrator', 'Budget exceeded, triggering cost optimization');
const optimized = await this.optimizeBudget(resolved);
resolved.set('task-budget', optimized);
}
return resolved;
}
/**
* 结果聚合:生成完整行程方案
*/
private async aggregateTripPlan(
results: Map<string, TaskResult>,
intent: TravelIntent
): Promise<TripPlan> {
const flight = results.get('task-flight')?.data;
const hotel = results.get('task-hotel')?.data;
const attractions = results.get('task-attraction')?.data;
const budget = results.get('task-budget')?.data;
const days = this.calculateDays(intent.departureDate, intent.returnDate);
const dailyPlans: DailyPlan[] = [];
for (let i = 0; i < days; i++) {
const dayAttractions = attractions?.dailyRoutes[i]?.attractions || [];
dailyPlans.push({
day: i + 1,
date: this.addDays(intent.departureDate, i),
attractions: dayAttractions,
meals: this.recommendMeals(dayAttractions),
transport: i === 0 ? flight?.outbound : (i === days - 1 ? flight?.inbound : 'local')
});
}
return {
summary: {
destination: intent.destination,
dates: { from: intent.departureDate, to: intent.returnDate },
travelers: intent.travelers,
totalCost: budget?.total || 0,
budgetStatus: budget?.status || 'unknown'
},
flights: flight,
hotel: hotel,
dailyPlans,
budgetBreakdown: budget?.breakdown,
tips: this.generateTips(intent, results)
};
}
/**
* 获取或创建Agent连接(连接池管理)
*/
private async getOrCreateConnection(agentId: string): Promise<AgentConnection> {
if (this.agentConnections.has(agentId)) {
return this.agentConnections.get(agentId)!;
}
const agent = this.availableAgents.get(agentId);
if (!agent) {
throw new Error(`Agent ${agentId} not available`);
}
const connection = await this.discoveryManager.connectToAgent(agentId);
this.agentConnections.set(agentId, connection);
return connection;
}
// ===== 辅助方法 =====
private calculateDays(start: string, end: string): number {
const startDate = new Date(start);
const endDate = new Date(end);
return Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)) + 1;
}
private addDays(date: string, days: number): string {
const d = new Date(date);
d.setDate(d.getDate() + days);
return d.toISOString().split('T')[0];
}
private calculateDistance(loc1: Location, loc2: Location): number {
// 简化版距离计算(实际使用地图API)
const R = 6371; // 地球半径km
const dLat = (loc2.lat - loc1.lat) * Math.PI / 180;
const dLon = (loc2.lng - loc1.lng) * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(loc1.lat * Math.PI / 180) * Math.cos(loc2.lat * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
}
private async negotiateHotelAdjustment(hotel: any, day: any): Promise<TaskResult> {
// 重新搜索更近的酒店
const connection = await this.getOrCreateConnection(
Array.from(this.availableAgents.values()).find(a => a.agentInfo.type === 'hotel')!.agentInfo.id
);
return await connection.invoke('reSearch', {
originalHotel: hotel,
constraint: { maxDistanceFrom: day.attractions[0].location, maxDistanceKm: 15 }
});
}
private async optimizeBudget(results: Map<string, TaskResult>): Promise<TaskResult> {
// 预算优化逻辑:推荐更经济的选项
return {
status: 'optimized',
data: {
total: 0,
status: 'optimized',
breakdown: {},
savings: []
}
};
}
private recommendMeals(attractions: any[]): MealRecommendation[] {
return attractions.map(a => ({
location: a.location,
type: a.type === 'cultural' ? 'local_cuisine' : 'casual'
}));
}
private generateTips(intent: TravelIntent, results: Map<string, TaskResult>): string[] {
const tips: string[] = [];
const budget = results.get('task-budget')?.data;
if (budget?.status === 'over') {
tips.push('💡 预算紧张,建议提前预订机票和酒店以获取更优价格');
}
if (intent.preferences.includes('亲子')) {
tips.push('👨👩👧 已为您筛选亲子友好型酒店和景点');
}
return tips;
}
}
// ===== 类型定义 =====
interface TravelIntent {
origin: string;
destination: string;
departureDate: string;
returnDate: string;
travelers: number;
budget?: number;
preferences: string[];
rawRequest: string;
}
interface SubTask {
id: string;
type: string;
description: string;
parameters: any;
requiredCapabilities: string[];
priority: number;
dependsOn?: string[];
}
interface AgentProposal {
agentId: string;
agentName: string;
deviceName: string;
estimatedCost: number;
estimatedTime: number;
confidence: number;
proposalData: any;
score?: number;
}
interface TaskAssignment {
task: SubTask;
assignedAgent: AgentProposal;
status: string;
}
interface TaskResult {
status: string;
data: any;
}
interface TripPlan {
summary: TripSummary;
flights: any;
hotel: any;
dailyPlans: DailyPlan[];
budgetBreakdown: any;
tips: string[];
}
interface TripSummary {
destination: string;
dates: { from: string; to: string };
travelers: number;
totalCost: number;
budgetStatus: string;
}
interface DailyPlan {
day: number;
date: string;
attractions: any[];
meals: MealRecommendation[];
transport: string;
}
interface MealRecommendation {
location: Location;
type: string;
}
interface Location {
lat: number;
lng: number;
}
enum ExecutionState {
IDLE = 'idle',
PLANNING = 'planning',
EXECUTING = 'executing',
NEGOTIATING = 'negotiating',
AGGREGATING = 'aggregating',
COMPLETED = 'completed',
FAILED = 'failed'
}
3.4 专业智能体实现:以机票Agent为例
// src/agents/FlightAgent.ts
import { distributedHardware } from '@kit.DistributedHardwareKit';
/**
* 机票智能体
* 部署在手机端,负责航班查询、比价、预订
*/
export class FlightAgent {
private serviceId: string;
constructor() {
this.serviceId = `agent://flight/${deviceInfo.deviceId}`;
}
/**
* 初始化并注册服务
*/
async initialize(): Promise<void> {
// 注册到分布式软总线
await distributedHardware.registerService({
serviceId: this.serviceId,
serviceType: 'agent',
capabilities: ['flight_search', 'price_compare', 'booking'],
properties: {
agentType: 'flight',
agentName: '机票助手',
supportedAirlines: ['CA', 'MU', 'CZ', 'HU'],
maxConcurrentTasks: 3
}
});
// 注册RPC方法处理器
distributedHardware.onRpcCall(this.serviceId, async (method: string, params: any) => {
switch (method) {
case 'bid': return this.handleBid(params);
case 'execute': return this.handleExecute(params);
default: throw new Error(`Unknown method: ${method}`);
}
});
}
/**
* 处理招标请求(合同网协议)
*/
private async handleBid(params: any): Promise<any> {
const { taskType, parameters } = params;
// 评估自身能力
if (taskType !== 'flight_search') {
return { canHandle: false, reason: 'Unsupported task type' };
}
// 估算成本和置信度
const origin = parameters.origin;
const destination = parameters.destination;
// 检查航线覆盖
const isRouteSupported = await this.checkRouteSupport(origin, destination);
if (!isRouteSupported) {
return { canHandle: false, reason: 'Route not supported' };
}
// 模拟投标评估
const estimatedCost = 100; // 计算资源成本
const estimatedTime = 3000; // 预计3秒完成
const confidence = 0.95; // 高置信度
return {
canHandle: true,
estimatedCost,
estimatedTime,
confidence,
agentInfo: {
name: '机票助手',
device: deviceInfo.deviceName,
features: ['实时价格', '多航司比价', '退改签保障']
}
};
}
/**
* 执行任务
*/
private async handleExecute(params: any): Promise<TaskResult> {
const { taskId, parameters } = params;
hilog.info(0x0000, 'FlightAgent', `Executing task: ${taskId}`);
try {
// 1. 查询航班
const flights = await this.searchFlights(parameters);
// 2. 价格比较
const compared = this.comparePrices(flights);
// 3. 推荐最优方案
const recommended = this.recommendFlights(compared, parameters);
return {
status: 'success',
data: {
outbound: recommended.outbound,
inbound: recommended.inbound,
alternatives: recommended.alternatives,
totalPrice: recommended.totalPrice,
bookingUrl: recommended.bookingUrl
}
};
} catch (err) {
return {
status: 'failed',
error: err.message
};
}
}
private async searchFlights(params: any): Promise<Flight[]> {
// 调用航司API或OTA接口
// 实际实现需要对接真实数据源
return [
{
flightNo: 'CA1234',
airline: '中国国际航空',
departure: { airport: 'PEK', time: '08:00' },
arrival: { airport: 'SYX', time: '12:30' },
price: 1280,
class: '经济舱',
stops: 0
},
{
flightNo: 'MU5678',
airline: '东方航空',
departure: { airport: 'PKX', time: '10:30' },
arrival: { airport: 'SYX', time: '15:00' },
price: 1150,
class: '经济舱',
stops: 1
}
];
}
private comparePrices(flights: Flight[]): Flight[] {
return flights.sort((a, b) => a.price - b.price);
}
private recommendFlights(flights: Flight[], params: any): any {
const best = flights[0]; // 最优价格
return {
outbound: best,
inbound: { ...best, flightNo: best.flightNo + 'R' }, // 简化处理
alternatives: flights.slice(1, 4),
totalPrice: best.price * params.travelers * 2 // 往返
};
}
private async checkRouteSupport(origin: string, destination: string): Promise<boolean> {
// 检查是否支持该航线
const supportedRoutes = ['北京-三亚', '上海-三亚', '广州-三亚'];
return supportedRoutes.includes(`${origin}-${destination}`);
}
}
interface Flight {
flightNo: string;
airline: string;
departure: { airport: string; time: string };
arrival: { airport: string; time: string };
price: number;
class: string;
stops: number;
}
3.5 跨设备沉浸光感协作看板(PC端)
// src/pc/TravelDashboard.ets
import { TravelMasterOrchestrator } from '../agents/TravelMasterOrchestrator';
import { LightEffectManager } from '../effects/LightEffectManager';
/**
* PC端旅行规划看板
* 特点:
* 1. 大屏沉浸式展示完整行程
* 2. 实时显示多智能体协作状态
* 3. 动态光感反映协作进度
* 4. 支持拖拽调整行程
*/
@Entry
@Component
struct TravelDashboard {
@State tripPlan: TripPlan | null = null;
@State collaborationState: CollaborationState = CollaborationState.IDLE;
@State agentStates: Map<string, AgentStateInfo> = new Map();
@State selectedDay: number = 1;
private orchestrator: TravelMasterOrchestrator;
aboutToAppear() {
this.orchestrator = new TravelMasterOrchestrator();
this.orchestrator.initialize();
// 监听协作状态变化
this.orchestrator.onStateChange((state) => {
this.collaborationState = state;
this.updateLightEffect(state);
});
}
build() {
Column() {
// 顶部标题栏
this.Header()
if (!this.tripPlan) {
// 输入区域
this.InputSection()
} else {
// 行程看板
this.TripBoard()
}
// 底部协作状态栏
this.CollaborationStatusBar()
}
.width('100%')
.height('100%')
.backgroundColor('#0A0A0F') // 深色背景,光感更明显
}
@Builder
Header() {
Row() {
Text('🧳 鸿蒙智能旅行')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
// 协作状态指示灯
Circle()
.width(12)
.height(12)
.fill(this.getStateColor())
.shadow({
radius: 8,
color: this.getStateColor(0.6),
offsetY: 0
})
.animation({
duration: 1000,
iterations: -1,
curve: Curve.EaseInOut
})
Text(this.getStateText())
.fontSize(14)
.fontColor(this.getStateColor())
}
.width('100%')
.height(64)
.padding({ left: 32, right: 32 })
.justifyContent(FlexAlign.SpaceBetween)
.backgroundColor('rgba(255,255,255,0.05)')
.backdropBlur(20)
}
@Builder
InputSection() {
Column() {
Text('告诉旅行管家你的计划')
.fontSize(20)
.fontColor('#FFFFFF')
.margin({ bottom: 24 })
// 快捷标签
Row({ space: 12 }) {
ForEach(['北京→三亚 5天', '上海→成都 3天', '广州→丽江 7天'], (tag: string) => {
Text(tag)
.fontSize(14)
.fontColor('#4A90D9')
.padding({ left: 16, right: 16, top: 8, bottom: 8 })
.backgroundColor('rgba(74, 144, 217, 0.15)')
.borderRadius(16)
.border({ width: 1, color: 'rgba(74, 144, 217, 0.3)' })
.onClick(() => this.startPlanning(tag))
})
}
.margin({ bottom: 24 })
// 自定义输入
TextInput({ placeholder: '例如:一家三口从北京去三亚玩5天,预算1万5,想看海和吃海鲜...' })
.width('60%')
.height(56)
.backgroundColor('rgba(255,255,255,0.08)')
.borderRadius(12)
.fontColor('#FFFFFF')
.placeholderColor('rgba(255,255,255,0.4)')
.onSubmit((value) => this.startPlanning(value))
}
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
}
@Builder
TripBoard() {
Row() {
// 左侧日期导航
this.DayNavigator()
// 中间行程详情
this.DayDetail()
// 右侧预算与智能体状态
this.SidePanel()
}
.width('100%')
.layoutWeight(1)
}
@Builder
DayNavigator() {
Column() {
ForEach(this.tripPlan?.dailyPlans || [], (day: DailyPlan, index: number) => {
Column() {
Text(`Day ${day.day}`)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(this.selectedDay === day.day ? '#FFFFFF' : 'rgba(255,255,255,0.5)')
Text(day.date)
.fontSize(12)
.fontColor('rgba(255,255,255,0.4)')
.margin({ top: 4 })
}
.width(120)
.height(80)
.backgroundColor(this.selectedDay === day.day ? 'rgba(74, 144, 217, 0.2)' : 'transparent')
.borderRadius(12)
.border({
width: { left: this.selectedDay === day.day ? 3 : 0 },
color: '#4A90D9'
})
.onClick(() => { this.selectedDay = day.day })
})
}
.width(140)
.height('100%')
.padding(16)
.backgroundColor('rgba(255,255,255,0.03)')
}
@Builder
DayDetail() {
Column() {
const day = this.tripPlan?.dailyPlans.find(d => d.day === this.selectedDay);
if (!day) return;
// 日期标题
Text(`${day.date} 第${day.day}天`)
.fontSize(24)
.fontColor('#FFFFFF')
.margin({ bottom: 16 })
// 景点卡片(带光感效果)
ForEach(day.attractions, (attraction: any) => {
this.AttractionCard(attraction)
})
// 餐饮推荐
if (day.meals.length > 0) {
Text('🍽️ 餐饮推荐')
.fontSize(16)
.fontColor('#FFFFFF')
.margin({ top: 16, bottom: 8 })
ForEach(day.meals, (meal: any) => {
Row() {
Text(meal.type === 'local_cuisine' ? '🥘 当地特色' : '🍜 简餐')
.fontSize(14)
.fontColor('rgba(255,255,255,0.7)')
}
.width('100%')
.height(48)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(8)
.padding({ left: 16 })
})
}
}
.layoutWeight(1)
.padding(24)
}
@Builder
AttractionCard(attraction: any) {
Row() {
// 景点图片(带光晕)
Stack() {
Image(attraction.image || $r('app.media.placeholder_attraction'))
.width(120)
.height(80)
.borderRadius(8)
.objectFit(ImageFit.Cover)
// 光感叠加
Column()
.width(120)
.height(80)
.backgroundColor('linear-gradient(to right, transparent, rgba(74, 144, 217, 0.3))')
.borderRadius(8)
}
Column() {
Text(attraction.name)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text(attraction.description || '热门景点')
.fontSize(13)
.fontColor('rgba(255,255,255,0.5)')
.margin({ top: 4 })
.maxLines(2)
Row() {
Text(`⭐ ${attraction.rating || 4.5}`)
.fontSize(12)
.fontColor('#FFD700')
Text(`⏱️ ${attraction.duration || '2小时'}`)
.fontSize(12)
.fontColor('rgba(255,255,255,0.4)')
.margin({ left: 12 })
}
.margin({ top: 8 })
}
.alignItems(HorizontalAlign.Start)
.margin({ left: 16 })
.layoutWeight(1)
}
.width('100%')
.height(100)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(12)
.padding(12)
.margin({ bottom: 12 })
.border({
width: 1,
color: 'rgba(74, 144, 217, 0.2)'
})
.shadow({
radius: 12,
color: 'rgba(74, 144, 217, 0.1)',
offsetY: 4
})
}
@Builder
SidePanel() {
Column() {
// 预算概览
this.BudgetCard()
// 智能体协作状态
this.AgentStatusPanel()
// 操作按钮
Button('导出行程')
.width('100%')
.height(48)
.backgroundColor('#4A90D9')
.fontColor('#FFFFFF')
.borderRadius(24)
.margin({ top: 24 })
.onClick(() => this.exportItinerary())
}
.width(280)
.height('100%')
.padding(24)
.backgroundColor('rgba(255,255,255,0.03)')
}
@Builder
BudgetCard() {
Column() {
Text('💰 预算概览')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.margin({ bottom: 12 })
// 预算环形图(简化版)
Stack() {
Circle()
.width(120)
.height(120)
.fill('none')
.stroke('rgba(255,255,255,0.1)')
.strokeWidth(8)
Circle()
.width(120)
.height(120)
.fill('none')
.stroke('#4A90D9')
.strokeWidth(8)
.strokeLineCap(LineCapStyle.Round)
.strokeDashArray([this.getBudgetProgress() * 3.77, 377]) // 2πr ≈ 377
Column() {
Text(`¥${this.tripPlan?.summary.totalCost || 0}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text(this.tripPlan?.summary.budgetStatus || '计算中')
.fontSize(12)
.fontColor(this.getBudgetColor())
}
}
.width(120)
.height(120)
.margin({ bottom: 16 })
// 费用明细
ForEach([
{ label: '✈️ 机票', value: this.tripPlan?.budgetBreakdown?.flight || 0, color: '#FF6B6B' },
{ label: '🏨 酒店', value: this.tripPlan?.budgetBreakdown?.hotel || 0, color: '#4ECDC4' },
{ label: '🎫 景点', value: this.tripPlan?.budgetBreakdown?.attraction || 0, color: '#FFD93D' },
{ label: '🍜 餐饮', value: this.tripPlan?.budgetBreakdown?.food || 0, color: '#95E1D3' }
], (item: any) => {
Row() {
Text(item.label)
.fontSize(13)
.fontColor('rgba(255,255,255,0.7)')
Text(`¥${item.value}`)
.fontSize(13)
.fontColor(item.color)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 8 })
})
}
.width('100%')
.padding(16)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(16)
.margin({ bottom: 16 })
}
@Builder
AgentStatusPanel() {
Column() {
Text('🤖 智能体协作')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.margin({ bottom: 12 })
ForEach(Array.from(this.agentStates.entries()), ([agentId, state]: [string, AgentStateInfo]) => {
Row() {
// Agent状态指示灯
Circle()
.width(8)
.height(8)
.fill(this.getAgentStateColor(state.status))
.shadow({
radius: 6,
color: this.getAgentStateColor(state.status, 0.5),
offsetY: 0
})
Column() {
Text(state.name)
.fontSize(13)
.fontColor('#FFFFFF')
Text(state.currentTask || '空闲')
.fontSize(11)
.fontColor('rgba(255,255,255,0.5)')
}
.alignItems(HorizontalAlign.Start)
.margin({ left: 12 })
.layoutWeight(1)
// 进度条
if (state.progress > 0) {
Progress({ value: state.progress, total: 100, type: ProgressType.Linear })
.width(60)
.height(4)
.color('#4A90D9')
.backgroundColor('rgba(255,255,255,0.1)')
}
}
.width('100%')
.height(48)
.backgroundColor('rgba(255,255,255,0.03)')
.borderRadius(8)
.padding({ left: 12, right: 12 })
.margin({ bottom: 8 })
})
}
.width('100%')
.padding(16)
.backgroundColor('rgba(255,255,255,0.05)')
.borderRadius(16)
}
@Builder
CollaborationStatusBar() {
Row() {
// 设备连接状态
Row({ space: 8 }) {
ForEach(['📱 手机', '💻 PC', '⌚ 手表'], (device: string) => {
Text(device)
.fontSize(12)
.fontColor('rgba(255,255,255,0.6)')
.padding({ left: 8, right: 8, top: 4, bottom: 4 })
.backgroundColor('rgba(255,255,255,0.08)')
.borderRadius(12)
})
}
// 实时协作日志
Text(this.getLastLog())
.fontSize(12)
.fontColor('rgba(255,255,255,0.4)')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.layoutWeight(1)
.margin({ left: 16, right: 16 })
}
.width('100%')
.height(40)
.padding({ left: 24, right: 24 })
.backgroundColor('rgba(0,0,0,0.3)')
}
// ===== 业务逻辑 =====
private async startPlanning(request: string): Promise<void> {
this.collaborationState = CollaborationState.PLANNING;
this.updateLightEffect(CollaborationState.PLANNING);
try {
const plan = await this.orchestrator.planTrip(request);
this.tripPlan = plan;
this.collaborationState = CollaborationState.COMPLETED;
} catch (err) {
this.collaborationState = CollaborationState.FAILED;
promptAction.showToast({ message: '规划失败,请重试' });
}
}
private updateLightEffect(state: CollaborationState): void {
const effectMap: Record<CollaborationState, { color: string; intensity: number }> = {
[CollaborationState.IDLE]: { color: '#4A90D9', intensity: 0.3 },
[CollaborationState.PLANNING]: { color: '#FFD93D', intensity: 0.7 },
[CollaborationState.EXECUTING]: { color: '#FF6B6B', intensity: 0.9 },
[CollaborationState.NEGOTIATING]: { color: '#95E1D3', intensity: 0.8 },
[CollaborationState.COMPLETED]: { color: '#4ECDC4', intensity: 0.6 },
[CollaborationState.FAILED]: { color: '#FF4757', intensity: 0.5 }
};
const effect = effectMap[state];
LightEffectManager.getInstance().render(
state === CollaborationState.EXECUTING ? 'excited' :
state === CollaborationState.COMPLETED ? 'warm' : 'professional',
effect.intensity
);
}
private getStateColor(alpha: number = 1): string {
const colors: Record<CollaborationState, string> = {
[CollaborationState.IDLE]: `rgba(74, 144, 217, ${alpha})`,
[CollaborationState.PLANNING]: `rgba(255, 217, 61, ${alpha})`,
[CollaborationState.EXECUTING]: `rgba(255, 107, 107, ${alpha})`,
[CollaborationState.NEGOTIATING]: `rgba(149, 225, 211, ${alpha})`,
[CollaborationState.COMPLETED]: `rgba(78, 205, 196, ${alpha})`,
[CollaborationState.FAILED]: `rgba(255, 71, 87, ${alpha})`
};
return colors[this.collaborationState];
}
private getStateText(): string {
const texts: Record<CollaborationState, string> = {
[CollaborationState.IDLE]: '等待输入',
[CollaborationState.PLANNING]: '意图拆解中...',
[CollaborationState.EXECUTING]: '多智能体协作执行中...',
[CollaborationState.NEGOTIATING]: '冲突协商中...',
[CollaborationState.COMPLETED]: '行程规划完成',
[CollaborationState.FAILED]: '执行失败'
};
return texts[this.collaborationState];
}
private getAgentStateColor(status: string, alpha: number = 1): string {
const colors: Record<string, string> = {
'idle': `rgba(128, 128, 128, ${alpha})`,
'working': `rgba(255, 217, 61, ${alpha})`,
'completed': `rgba(78, 205, 196, ${alpha})`,
'error': `rgba(255, 71, 87, ${alpha})`
};
return colors[status] || colors['idle'];
}
private getBudgetProgress(): number {
if (!this.tripPlan?.summary.totalCost || !this.tripPlan?.summary.budget) return 0;
return Math.min(this.tripPlan.summary.totalCost / this.tripPlan.summary.budget, 1);
}
private getBudgetColor(): string {
const progress = this.getBudgetProgress();
if (progress > 0.9) return '#FF6B6B';
if (progress > 0.7) return '#FFD93D';
return '#4ECDC4';
}
private getLastLog(): string {
return '机票Agent完成航班查询 | 酒店Agent搜索中...';
}
private exportItinerary(): void {
// 导出为PDF或分享
hilog.info(0x0000, 'Dashboard', 'Exporting itinerary...');
}
}
enum CollaborationState {
IDLE = 'idle',
PLANNING = 'planning',
EXECUTING = 'executing',
NEGOTIATING = 'negotiating',
COMPLETED = 'completed',
FAILED = 'failed'
}
interface AgentStateInfo {
name: string;
status: string;
currentTask?: string;
progress: number;
deviceName: string;
}
3.6 手机端悬浮导航入口
// src/phone/FloatTravelAgent.ets
import { TravelMasterOrchestrator } from '../agents/TravelMasterOrchestrator';
/**
* 手机端悬浮旅行Agent入口
* 作为多设备协作的触发器,长按语音输入后,自动将任务分发到各设备Agent
*/
@Entry
@Component
struct FloatTravelAgent {
@State isExpanded: boolean = false;
@State isListening: boolean = false;
@State recentPlans: TripPlan[] = [];
private orchestrator: TravelMasterOrchestrator;
aboutToAppear() {
this.orchestrator = new TravelMasterOrchestrator();
this.orchestrator.initialize();
}
build() {
Stack() {
if (this.isExpanded) {
// 展开面板
this.ExpandedPanel()
}
// 悬浮球
this.FloatBall()
}
.width('100%')
.height('100%')
.backgroundColor(this.isExpanded ? 'rgba(0,0,0,0.5)' : '#00000000')
.animation({ duration: 200 })
}
@Builder
FloatBall() {
Stack() {
// 光晕层
Circle()
.width(80)
.height(80)
.fill(this.isListening ? '#FFD93D' : '#4A90D9')
.opacity(0.2)
.blur(20)
.scale({ x: this.isListening ? 1.3 : 1.0, y: this.isListening ? 1.3 : 1.0 })
.animation({ duration: 1000, iterations: -1 })
Circle()
.width(64)
.height(64)
.fill('#FFFFFF')
.shadow({
radius: 12,
color: this.isListening ? 'rgba(255, 217, 61, 0.4)' : 'rgba(74, 144, 217, 0.4)',
offsetY: 4
})
Image(this.isListening ? $r('app.media.ic_mic') : $r('app.media.ic_travel'))
.width(32)
.height(32)
.fillColor(this.isListening ? '#FFD93D' : '#4A90D9')
}
.width(80)
.height(80)
.position({ x: 300, y: 600 })
.gesture(
GestureGroup(GestureMode.Sequence,
LongPressGesture({ duration: 500 })
.onAction(() => this.startVoiceInput()),
TapGesture()
.onAction(() => { this.isExpanded = !this.isExpanded })
)
)
}
@Builder
ExpandedPanel() {
Column() {
Text('🧳 鸿蒙智能旅行')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.margin({ top: 40, bottom: 24 })
// 快捷输入
TextInput({ placeholder: '想去哪里玩?' })
.width('90%')
.height(48)
.backgroundColor('rgba(255,255,255,0.1)')
.borderRadius(24)
.fontColor('#FFFFFF')
.placeholderColor('rgba(255,255,255,0.4)')
.onSubmit((value) => this.submitRequest(value))
// 最近行程
if (this.recentPlans.length > 0) {
Text('最近行程')
.fontSize(14)
.fontColor('rgba(255,255,255,0.6)')
.margin({ top: 24, bottom: 12 })
.alignSelf(ItemAlign.Start)
.margin({ left: '5%' })
List() {
ForEach(this.recentPlans, (plan: TripPlan) => {
ListItem() {
Row() {
Column() {
Text(plan.summary.destination)
.fontSize(16)
.fontColor('#FFFFFF')
Text(`${plan.summary.dates.from} ~ ${plan.summary.dates.to}`)
.fontSize(12)
.fontColor('rgba(255,255,255,0.5)')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
Text(`¥${plan.summary.totalCost}`)
.fontSize(14)
.fontColor('#4ECDC4')
}
.width('100%')
.height(64)
.backgroundColor('rgba(255,255,255,0.08)')
.borderRadius(12)
.padding({ left: 16, right: 16 })
}
})
}
.width('90%')
.height(200)
}
// 多设备提示
Row() {
Image($r('app.media.ic_devices'))
.width(20)
.height(20)
.fillColor('rgba(255,255,255,0.6)')
Text('将在手机、平板、PC上协同规划')
.fontSize(12)
.fontColor('rgba(255,255,255,0.6)')
.margin({ left: 8 })
}
.margin({ top: 24 })
}
.width('100%')
.height('70%')
.backgroundColor('#1A1A2E')
.borderRadius({ topLeft: 24, topRight: 24 })
.position({ y: '30%' })
}
private async startVoiceInput(): Promise<void> {
this.isListening = true;
// 语音识别...
setTimeout(() => {
this.isListening = false;
this.submitRequest('一家三口从北京去三亚玩5天');
}, 2000);
}
private async submitRequest(request: string): Promise<void> {
this.isExpanded = false;
// 触发多智能体协作
promptAction.showToast({ message: '正在协调多设备智能体...' });
}
}
四、运行效果与图片展示
4.1 鸿蒙PC应用多设备统一体验


上图展示了HarmonyOS PC应用与手机、平板统一的状态栏和交互体验。我们的旅行看板正是基于这种多端统一的UX设计,在PC大屏上展示完整行程,手机作为语音输入入口。
4.2 多智能体协作生态

华为Mate X7搭载的鸿蒙6首次商用多智能体协作,"小艺和TA的朋友们"涵盖旅行、购物、金融等垂域智能体。本文的机票Agent、酒店Agent、景点Agent正是这一生态的技术实现。
4.3 分布式软总线跨设备架构



分布式软总线是鸿蒙的核心底座,通过任务总线和数据总线实现摄像头、屏幕、存储、MIC等硬件能力的跨设备共享。本文的多智能体协作正是基于软总线的服务发现与RPC通信能力。
4.4 沉浸光感与游戏特效

HarmonyOS的沉浸光感特效系统不仅用于UI美化,更可应用于游戏和交互场景。本文PC端看板的动态光效正是借鉴了这一渲染管线。
五、关键技术总结
5.1 创新点
| 创新维度 | 具体实现 |
|---|---|
| 协作协议 | 基于合同网协议(CNP)的任务分配,支持多目标优化评分 |
| 分布式架构 | 智能体通过软总线自动发现,无需手动配置IP/端口 |
| 冲突解决 | 酒店-景点距离冲突检测 + 自动协商重搜索 |
| 状态可视化 | 协作状态 → 沉浸光感颜色/强度映射,"看得见"的AI思考 |
| 多端协同 | 手机语音输入 → 分布式任务分发 → PC大屏展示 |
5.2 性能优化
// 1. 连接池复用:避免重复建立跨设备连接
private agentConnections: Map<string, AgentConnection> = new Map();
// 2. 并行执行:无依赖任务同时发起
const promises = assignments.map(async (assignment) => { ... });
const results = await Promise.all(promises);
// 3. 增量更新:仅同步变化的状态
distributedObject.sync({
strategy: SyncStrategy.PUSH_ONLY_CHANGED,
interval: 500 // 500ms批量同步
});
5.3 扩展方向
- 垂域扩展:将机票/酒店/景点Agent替换为医疗/教育/办公Agent,快速构建行业解决方案
- 人机协作:引入"人在回路"机制,关键决策(如预算超支)需用户确认
- 模型优化:使用端侧大模型替代规则引擎,提升意图理解准确率
六、结语
本文通过HarmonyOS 6(API 23)的多智能体协作框架(MACF)、分布式软总线与沉浸光感三大核心能力的深度融合,展示了一种"一呼百应"的跨设备智能体集群架构。旅行管家Agent作为协调者,通过合同网协议将复杂任务智能分配给分布在手机、平板、PC上的专业Agent,实现了真正的"分布式AI"。
从代码层面看,关键创新在于:
- DeviceDiscoveryManager 实现了基于软总线的智能体自动发现与P2P连接
- TravelMasterOrchestrator 实现了意图拆解→招标→投标→执行→协商→聚合的完整协作闭环
- TravelDashboard 将抽象的协作状态转化为直观的沉浸光感可视化
这种架构不仅适用于旅行规划,更可扩展至企业级智能办公(HarmonyOS PC)、智慧医疗会诊、工业设备协同运维等场景。期待更多开发者基于MACF框架,构建出更具想象力的鸿蒙多智能体生态!
转载自:https://blog.csdn.net/u014727709/article/details/162384489
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐




所有评论(0)