HarmonyOS宠物邻里实战第18篇:小艺照护助手、本地知识库与智能体入口接入
HarmonyOS宠物邻里实战第18篇:小艺照护助手、本地知识库与智能体入口接入
摘要
宠物管理 App 做到档案、寄养、通知和社区之后,用户还会遇到一个很实际的问题:档案里已经有疫苗、驱虫、饮食、外出和清洁信息,但用户不知道下一步该记录什么、怎么补全、怎么把这些信息转成可执行的照护建议。宠物邻里项目里,我把这件事拆成两层:App 内置一个轻量本地智能体,保证没有平台配置也能回答基础问题;同时预留小艺开放平台智能体入口,后续写入 agentId 和 launchUri 后可以拉起平台侧“宠物照护助手”。
本文基于宠物邻里 HarmonyOS + ArkTS 项目,复盘小艺照护助手的工程实现:
XiaoyiKnowledgeDatabase如何维护独立基础问答库;XiaoyiPetAgentService如何组合宠物档案和知识库;XiaoyiAgentPage如何渲染快捷问题、消息气泡和发送框;XiaoyiAgentConfig如何预留平台侧agentId、launchUri和知识库版本;- 本地智能体和平台智能体如何分层;
- 如何设计匹配算法、兜底回答和能力边界;
- 最后给出上线前验收清单。
这篇文章重点是“可落地的智能体接入”。不是一上来就追求复杂模型,而是先让 App 具备可解释、可测试、可回退的本地问答能力。
工程背景与源码定位
| 文件 | 作用 |
|---|---|
MyApp/entry/src/main/ets/pages/agent/XiaoyiAgentPage.ets |
小艺智能体页面,负责消息、快捷问题和平台入口 |
MyApp/entry/src/main/ets/services/XiaoyiPetAgentService.ets |
本地智能体服务,组合宠物档案和知识库回答 |
MyApp/entry/src/main/ets/services/XiaoyiKnowledgeDatabase.ets |
独立基础问答知识库 |
MyApp/entry/src/main/ets/common/XiaoyiAgentConfig.ets |
小艺开放平台配置 |
MyApp/docs/xiaoyi-agent.md |
平台侧智能体搭建说明 |
MyApp/docs/xiaoyi-agent-knowledge-base.json |
可导入平台的知识库材料 |
MyApp/entry/src/main/ets/common/MockStore.ets |
本地宠物档案数据来源 |
MyApp/entry/src/main/ets/pages/home/HomeTab.ets |
首页入口 |
MyApp/entry/src/main/ets/pages/user/SettingsPage.ets |
设置页入口 |
环境信息:
| 项目 | 值 |
|---|---|
| HarmonyOS 工程模型 | Stage 模型 |
| ArkTS 页面 | NavDestination、@State、@Builder |
| target SDK | 6.0.2(22) |
| 本地知识库版本 | pet-care-agent-v1 |
| 平台侧智能体名称 | 宠物照护助手 |
| 知识库名称 | 宠物基础照护问答库 |
版本兼容性要提前说明:本文的 common.UIAbilityContext、Want、startAbility、NavDestinationContext、TextArea.onChange 和 @State 刷新行为基于当前工程验证。升级 HarmonyOS SDK 后,要重点回归页面生命周期、Want 拉起参数和输入框状态刷新。

一、为什么要先做本地智能体
很多项目接入智能体时会先依赖平台侧配置,但移动端项目有几个现实约束:
| 问题 | 影响 |
|---|---|
平台 agentId 还没审核 |
页面入口不能完全阻塞 |
| 真机、账号、地区、权限不稳定 | 开发阶段难以每次验证 |
| 知识库内容还在调整 | 直接上线容易回答不一致 |
| 用户宠物档案属于 App 本地业务数据 | 平台侧知识库不能直接替代用户上下文 |
所以更稳的做法是分层:
HarmonyOS 页面
-> 本地智能体服务 XiaoyiPetAgentService
-> 本地知识库 XiaoyiKnowledgeDatabase
-> 平台配置 XiaoyiAgentConfig
-> 可选拉起小艺开放平台智能体
本地智能体负责开发期和弱网场景可用,平台智能体负责后续扩展能力。
二、配置文件设计
平台侧配置集中在 XiaoyiAgentConfig.ets:
export class XiaoyiAgentConfig {
static readonly agentId: string = '';
static readonly launchUri: string = '';
static readonly agentName: string = '宠物照护助手';
static readonly knowledgeBaseName: string = '宠物基础照护问答库';
static readonly promptVersion: string = 'pet-care-agent-v1';
static readonly queryText: string = '帮我查看宠物档案、照护提醒和日常照护记录';
static readonly source: string = 'pet-care-app';
static isConfigured(): boolean {
return XiaoyiAgentConfig.agentId.trim().length > 0;
}
static canLaunch(): boolean {
return XiaoyiAgentConfig.launchUri.trim().length > 0;
}
}
这里把平台参数和业务文案拆开:
| 字段 | 含义 |
|---|---|
agentId |
小艺开放平台创建智能体后的 ID |
launchUri |
平台提供的测试或发布启动链接 |
agentName |
页面展示名称 |
knowledgeBaseName |
平台侧知识库名称 |
promptVersion |
知识库和提示词版本 |
queryText |
拉起时传给智能体的默认问题 |
source |
来源标记,便于后续统计 |
配置文件的好处是页面不用硬编码平台参数。没有配置时,本地智能体照常可用;配置完成后再打开平台入口。
三、页面状态判断
XiaoyiAgentPage 进入页面后先刷新状态:
private refreshStatus(): void {
if (!XiaoyiAgentConfig.isConfigured()) {
this.statusText = '本地智能体已可用;小艺开放平台的 agentId 尚未写入配置。';
return;
}
if (!XiaoyiAgentConfig.canLaunch()) {
this.statusText = '本地智能体已可用;agentId 已配置,等待写入小艺开放平台提供的测试/发布启动链接。';
return;
}
this.statusText = '本地智能体已可用,也可在支持小艺能力的真机上拉起官网智能体。';
}
这段判断覆盖三个阶段:
| 阶段 | 页面状态 |
|---|---|
未配置 agentId |
本地智能体可用,平台入口待配置 |
已配置 agentId 但无 launchUri |
本地智能体可用,平台入口待链接 |
已配置 launchUri |
本地智能体和平台入口都可测试 |
开发期最怕页面直接显示“不可用”。这里用状态说明把能力边界讲清楚,用户仍然能使用本地问答。
四、本地智能体启动
页面初始化:
aboutToAppear(): void {
this.refreshStatus();
this.bootstrapAgent();
}
启动本地智能体:
private bootstrapAgent(): void {
const pets: Pet[] = MockStore.petsOf(MockStore.meId);
this.knowledgeText = XiaoyiPetAgentService.knowledgeSummary();
const welcome: XiaoyiAgentMessage = new XiaoyiAgentMessage();
welcome.id = 'welcome';
welcome.role = 'agent';
welcome.text = XiaoyiPetAgentService.welcome(pets);
this.messages = [welcome];
this.quickQuestions = XiaoyiPetAgentService.quickQuestions(pets);
}
这里读了两类数据:
| 数据 | 来源 | 用途 |
|---|---|---|
| 宠物档案 | MockStore.petsOf(MockStore.meId) |
个性化回答、档案检查、提醒建议 |
| 知识库摘要 | XiaoyiKnowledgeDatabase |
展示当前问答库规模和覆盖分类 |
如果用户还没有宠物档案,智能体仍然可以回答通用养宠问题;如果已有宠物档案,就能生成更贴合的档案建议。
五、消息模型
本地消息模型很轻:
export class XiaoyiAgentMessage {
id: string = '';
role: string = 'agent';
text: string = '';
}
快捷问题模型:
export class XiaoyiQuickQuestion {
title: string = '';
question: string = '';
}
这两个模型不依赖平台 SDK,页面可以直接渲染。后续如果接入真正的流式回复,也可以扩展 status、createdAt、errorText、traceId 等字段。
六、欢迎语
欢迎语根据宠物档案数量变化:
static welcome(pets: Pet[]): string {
if (pets.length === 0) {
return '你好,我是宠物照护助手。你可以先添加宠物档案,我会帮你梳理疫苗、驱虫、饮食、洗护和日常提醒要点;也可以直接问我宠物喂养、清洁、外出和新手照护的基础问题。';
}
return '你好,我是宠物照护助手。当前已读取到 ' + pets.length.toString() +
' 只宠物档案,可以帮你检查待完善信息、生成日常照护提醒,也能回答基础养宠问题。';
}
这一步看似只是文案,其实是在建立能力边界:
- 没有档案时,引导用户先添加档案;
- 有档案时,强调可以做档案检查和提醒;
- 两种情况下都支持基础问答。
智能体页面不能只说“你想问什么”,要告诉用户当前能做什么。
七、快捷问题设计
快捷问题由服务层生成:
static quickQuestions(pets: Pet[]): XiaoyiQuickQuestion[] {
const items: XiaoyiQuickQuestion[] = [];
if (pets.length > 0) {
items.push(XiaoyiPetAgentService.quick(pets[0].name + '建议', '根据' + pets[0].name + '的档案给我照护建议'));
}
items.push(XiaoyiPetAgentService.quick('档案检查', '帮我检查宠物档案还缺哪些照护信息'));
items.push(XiaoyiPetAgentService.quick('今日提醒', '今天有哪些宠物照护事项需要记录'));
items.push(XiaoyiPetAgentService.quick('饮食清洁', '帮我整理饮食和清洁方面的记录建议'));
items.push(XiaoyiPetAgentService.quick('新手准备', '新手养宠需要准备什么'));
items.push(XiaoyiPetAgentService.quick('疫苗记录', '疫苗记录应该怎么填'));
return items;
}
页面渲染:
@Builder QuickQuestionBar() {
Scroll() {
Row() {
ForEach(this.quickQuestions, (item: XiaoyiQuickQuestion) => {
Text(item.title)
.fontSize(FontSize.sm)
.fontColor($r('app.color.brand_primary'))
.fontWeight(FontWeight.Medium)
.padding({ left: Spacing.md, right: Spacing.md, top: 9, bottom: 9 })
.backgroundColor($r('app.color.brand_tint'))
.borderRadius(Radius.pill)
.margin({ right: Spacing.sm })
.onClick(() => { this.ask(item.question); })
}, (item: XiaoyiQuickQuestion) => item.title)
}
.padding({ top: Spacing.sm, bottom: Spacing.sm })
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
}
快捷问题不是装饰,它能降低用户试错成本。尤其是智能体刚上线时,用户不知道怎么问,推荐问题能把用户带到已验证路径。
八、发送消息流程
发送逻辑:
private ask(question: string): void {
const clean: string = question.trim();
if (clean.length === 0) {
return;
}
const user: XiaoyiAgentMessage = new XiaoyiAgentMessage();
user.id = 'u_' + Date.now().toString();
user.role = 'user';
user.text = clean;
const answer: XiaoyiAgentMessage = new XiaoyiAgentMessage();
answer.id = 'a_' + Date.now().toString();
answer.role = 'agent';
answer.text = XiaoyiPetAgentService.reply(clean, MockStore.petsOf(MockStore.meId));
this.messages = this.messages.concat([user, answer]);
this.draft = '';
}
这里有三个细节:
trim()后空内容不发送;- 用户消息和智能体回答都追加到
messages; - 回答时实时读取
MockStore.petsOf(MockStore.meId),避免宠物档案刷新后仍用旧数据。
本地智能体不是异步请求,所以页面体验会很快。后续接平台接口时,可以把回答部分改成异步 Promise。
九、消息气泡
消息气泡根据角色左右分布:
@Builder MessageBubble(message: XiaoyiAgentMessage) {
Row() {
if (message.role === 'user') {
Blank().layoutWeight(1)
}
Text(message.text)
.fontSize(FontSize.sm)
.fontColor(message.role === 'user' ? $r('app.color.text_on_primary') : $r('app.color.text_primary'))
.lineHeight(21)
.padding(Spacing.md)
.constraintSize({ maxWidth: '82%' })
.backgroundColor(message.role === 'user' ? $r('app.color.brand_primary') : $r('app.color.surface_card'))
.borderRadius(Radius.lg)
if (message.role !== 'user') {
Blank().layoutWeight(1)
}
}
.width('100%')
.margin({ top: Spacing.sm })
}
最大宽度限制为 82%,可以避免长文本气泡挤满整行。回答内容支持换行,因为 Text 会按字符串里的换行展示。
十、输入框与操作区
输入框:
TextArea({ placeholder: '问我宠物档案、提醒、饮食、清洁、外出或基础养宠问题', text: this.draft })
.height(86)
.maxLength(500)
.fontSize(FontSize.md)
.placeholderColor($r('app.color.text_placeholder'))
.backgroundColor($r('app.color.surface_alt'))
.borderRadius(Radius.md)
.margin({ top: Spacing.md })
.onChange((value: string) => { this.draft = value; })
按钮区:
Row() {
SecondaryButton({
label: '刷新档案',
onTap: () => { this.bootstrapAgent(); }
})
.layoutWeight(1)
Blank().width(Spacing.md)
PrimaryButton({
label: '发送',
onTap: () => { this.ask(this.draft); }
})
.layoutWeight(1)
}
刷新档案 很重要。宠物档案可能在其他页面被修改,用户回到智能体页后可以手动刷新上下文。
十一、本地知识库结构
知识库条目模型:
export class XiaoyiKnowledgeEntry {
id: string = '';
category: string = '';
question: string = '';
answer: string = '';
keywords: string[] = [];
}
每条知识包含:
| 字段 | 作用 |
|---|---|
id |
稳定编号,便于导入平台 |
category |
分类,例如新手照护、喂养、清洁 |
question |
标准问题 |
answer |
标准回答 |
keywords |
匹配关键词 |
知识库初始化:
private static readonly records: XiaoyiKnowledgeEntry[] = XiaoyiKnowledgeDatabase.seed();
这说明当前版本是内置静态知识库,不依赖网络。上线前可以把同样数据导出为 JSON,导入小艺开放平台知识库。
十二、知识库统计
统计条数:
static count(): number {
return XiaoyiKnowledgeDatabase.records.length;
}
统计分类:
static categories(): string[] {
const out: string[] = [];
for (let i = 0; i < XiaoyiKnowledgeDatabase.records.length; i++) {
const category: string = XiaoyiKnowledgeDatabase.records[i].category;
if (out.indexOf(category) < 0) {
out.push(category);
}
}
return out;
}
服务层展示摘要:
static knowledgeSummary(): string {
return '独立知识库已加载 ' + XiaoyiKnowledgeDatabase.count().toString() +
' 条基础问答,覆盖:' + XiaoyiKnowledgeDatabase.categories().join('、') + '。';
}
用户能看到知识库已加载多少条、覆盖哪些分类,这比黑盒式回答更可信。
十三、匹配算法
搜索入口:
static search(question: string): XiaoyiKnowledgeEntry | null {
const text: string = question.trim();
if (text.length === 0) {
return null;
}
let best: XiaoyiKnowledgeEntry | null = null;
let bestScore: number = 0;
for (let i = 0; i < XiaoyiKnowledgeDatabase.records.length; i++) {
const record: XiaoyiKnowledgeEntry = XiaoyiKnowledgeDatabase.records[i];
const score: number = XiaoyiKnowledgeDatabase.score(record, text);
if (score > bestScore) {
bestScore = score;
best = record;
}
}
return bestScore >= 2 ? best : null;
}
计分逻辑:
private static score(record: XiaoyiKnowledgeEntry, question: string): number {
let value: number = 0;
if (question.includes(record.question)) {
value += 5;
}
for (let i = 0; i < record.keywords.length; i++) {
if (question.includes(record.keywords[i])) {
value += 2;
}
}
if (question.includes(record.category)) {
value += 1;
}
return value;
}
当前算法很朴素,但有两个优点:
- 结果可解释,命中哪个关键词能看出来;
- 失败可兜底,不会胡乱返回不相关答案。
bestScore >= 2 意味着至少命中一个关键词才返回知识库答案。
十四、知识库问答示例
知识库里的新手照护条目:
XiaoyiKnowledgeDatabase.item(
'kb_pet_001',
'新手照护',
'新手养宠需要准备什么',
'新手养宠可以先准备四类内容:1. 基础用品:食盆、水碗、牵引或猫砂盆、清洁用品。2. 档案信息:品种、年龄、体重、疫苗和驱虫记录。3. 日常规则:固定喂食、清洁、外出和休息区域。4. 观察记录:饮食、排便、精神状态和体重变化。建议把这些内容同步记录到宠物档案里,后续提醒会更准确。',
['新手', '准备', '用品', '刚养', '养宠']
)
疫苗记录条目:
XiaoyiKnowledgeDatabase.item(
'kb_pet_007',
'疫苗',
'疫苗记录应该怎么填',
'疫苗记录建议包含接种日期、疫苗类型、接种机构和下次建议时间。若不确定历史记录,可以先写“待确认”,再根据疫苗本或机构记录补全。完整记录有助于后续生成更清楚的照护提醒。',
['疫苗', '接种', '疫苗本', '记录']
)
这些回答都避免给出医疗诊断,只做日常记录建议。智能体的边界要保守,特别是宠物健康类问题,不能替代专业机构。
十五、回答路由
服务层的 reply 先处理业务上下文,再查知识库:
static reply(question: string, pets: Pet[]): string {
const text: string = question.trim();
if (text.length === 0) {
return '可以直接问我宠物档案、照护提醒、饮食、清洁或外出习惯相关问题。';
}
if (text.includes('档案') || text.includes('缺') || text.includes('补全')) {
return XiaoyiPetAgentService.profileAnswer(pets);
}
if (text.includes('提醒') || text.includes('今天')) {
return XiaoyiPetAgentService.reminderAnswer(pets);
}
const knowledgeAnswer: string = XiaoyiKnowledgeDatabase.answer(text);
if (knowledgeAnswer.length > 0) {
return knowledgeAnswer;
}
if (text.includes('疫苗') || text.includes('驱虫')) {
return XiaoyiPetAgentService.reminderAnswer(pets);
}
if (text.includes('饮食') || text.includes('清洁') || text.includes('洗') || text.includes('外出') || text.includes('遛')) {
return XiaoyiPetAgentService.dailyCareAnswer(pets);
}
return XiaoyiPetAgentService.generalAnswer(pets);
}
顺序很关键:
- 空问题先返回输入提示;
- 档案类问题优先走宠物档案;
- 今日提醒优先走提醒模板;
- 再查独立知识库;
- 疫苗、驱虫、饮食、清洁做兜底;
- 最后返回通用能力说明。
这样可以避免“档案检查”被知识库里的通用词误命中。
十六、档案检查回答
档案检查逻辑:
private static profileAnswer(pets: Pet[]): string {
if (pets.length === 0) {
return '目前还没有宠物档案。建议先添加:昵称、品种、年龄、体重、疫苗记录、驱虫记录、饮食习惯、外出习惯、清洁习惯和注意事项。';
}
let answer: string = '我检查了当前宠物档案,建议优先补全这些信息:';
for (let i = 0; i < pets.length; i++) {
const pet: Pet = pets[i];
const missing: string[] = [];
if (pet.vaccineRecord.trim().length === 0) missing.push('疫苗记录');
if (pet.dewormRecord.trim().length === 0) missing.push('驱虫记录');
if (pet.dietHabit.trim().length === 0) missing.push('饮食习惯');
if (pet.walkHabit.trim().length === 0) missing.push('外出习惯');
if (pet.bathHabit.trim().length === 0) missing.push('清洁习惯');
if (pet.notes.trim().length === 0) missing.push('注意事项');
answer += '\n' + pet.name + ':' + (missing.length === 0 ? '档案较完整,可继续记录日常变化。' : missing.join('、'));
}
return answer;
}
这段逻辑利用了 App 已有数据,而不是只返回通用建议。用户问“档案还缺什么”,回答会列出每只宠物缺少的字段。
十七、今日提醒回答
提醒回答:
private static reminderAnswer(pets: Pet[]): string {
if (pets.length === 0) {
return '添加宠物档案后,我会按疫苗、驱虫、饮食和注意事项生成提醒。现在可以先准备最近一次疫苗时间、驱虫周期和常用主粮信息。';
}
return '今日建议记录三类事项:\n' +
'1. 基础照护:饮水、喂食、排便、外出牵引和清洁状态。\n' +
'2. 定期事项:疫苗记录、驱虫记录、洗护周期和体重变化。\n' +
'3. 档案更新:体重、照片、饮食变化和临时注意事项。';
}
这里没有尝试生成真正的日历提醒,而是先给出记录建议。后续可以接入本地通知或日程能力,把提醒从文本建议升级成可执行任务。
十八、日常照护回答
日常照护:
private static dailyCareAnswer(pets: Pet[]): string {
const petName: string = pets.length > 0 ? pets[0].name : '宠物';
return petName + ' 的日常记录可以按这几项整理:\n' +
'1. 饮食:主粮品牌、单次喂食量、喂食时间和饮水情况。\n' +
'2. 外出:外出时间、牵引状态、排便情况和回家清洁。\n' +
'3. 清洁:洗澡、梳毛、耳部和爪部清洁周期。\n' +
'4. 备注:当天特殊变化和下次需要提醒自己的事项。';
}
有宠物档案时会带上宠物名,没有档案时用“宠物”兜底。这样回答不会因为缺少数据而中断。
十九、平台入口
页面里的平台入口:
@Builder PlatformEntry() {
Column() {
Row() {
Text(XiaoyiAgentConfig.agentName)
.fontSize(FontSize.lg)
.fontWeight(FontWeight.Medium)
.fontColor($r('app.color.text_primary'))
.layoutWeight(1)
Tag({
text: XiaoyiAgentConfig.canLaunch() ? '可测试' : (XiaoyiAgentConfig.isConfigured() ? '待链接' : '待配置'),
tone: XiaoyiAgentConfig.canLaunch() ? TagTone.Success : TagTone.Info
})
}
.width('100%')
}
}
根据配置状态展示:
| 配置状态 | 标签 |
|---|---|
launchUri 存在 |
可测试 |
只有 agentId |
待链接 |
| 都没有 | 待配置 |
这样测试人员不用打开代码,也能从页面看出当前配置阶段。
二十、拉起小艺智能体
拉起逻辑:
private launchAgent(): void {
if (!XiaoyiAgentConfig.canLaunch()) {
this.statusText = '请先在 XiaoyiAgentConfig.ets 中写入小艺平台提供的 launchUri。';
return;
}
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
const want: Want = {
action: 'ohos.want.action.viewData',
uri: XiaoyiAgentConfig.launchUri,
parameters: {
agentId: XiaoyiAgentConfig.agentId,
queryText: XiaoyiAgentConfig.queryText,
source: XiaoyiAgentConfig.source
}
};
context.startAbility(want)
.then(() => {
this.statusText = '已请求拉起小艺智能体。';
})
.catch(() => {
this.statusText = '拉起失败,请确认 launchUri、应用关联、系统版本和当前账号测试权限。';
});
}
这里要检查四件事:
launchUri是否来自平台配置;agentId是否和平台侧智能体一致;- 应用包名和签名是否已经关联;
- 真机系统版本和账号是否有测试权限。
失败时不要只显示“启动失败”,要提示排查方向。
二十一、平台侧智能体配置
docs/xiaoyi-agent.md 中定义了平台侧信息:
| 项目 | 内容 |
|---|---|
| 智能体名称 | 宠物照护助手 |
| 一句话简介 | 帮助用户管理宠物档案、日常照护提醒、饮食、清洁、外出习惯记录,并回答基础养宠问题 |
| 服务对象 | 宠物主人 |
| 知识库名称 | 宠物基础照护问答库 |
| 知识库版本 | pet-care-agent-v1 |
| 能力边界 | 不扩展到当前应用以外的业务场景 |
平台侧提示词可以保持保守:
你是“宠物照护助手”,服务于一款宠物管理 HarmonyOS 应用。
回答时先确认宠物种类、年龄、体重、疫苗/驱虫记录和当前日常照护场景。
对喂养、外出、洗护、疫苗、驱虫和档案补全问题,给出清晰的步骤化建议。
当用户信息不足时,引导用户回到应用补全宠物档案。
保护隐私,不要求用户公开身份证号、详细住址、电话等敏感信息。
基础养宠问答优先参考“宠物基础照护问答库”,不要编造平台知识库之外的专业结论。
智能体能力边界要写进配置文档,而不是只靠开发口头约定。
二十二、知识库同步到平台
当前 App 侧知识库文件是:
entry/src/main/ets/services/XiaoyiKnowledgeDatabase.ets
平台侧导入材料是:
docs/xiaoyi-agent-knowledge-base.json
同步规则:
| App 字段 | 平台字段 |
|---|---|
id |
记录编号 |
category |
分类 |
question |
问题 |
answer |
答案 |
keywords |
关键词 |
建议每次更新知识库后同步修改 promptVersion 或知识库版本号。例如:
static readonly promptVersion: string = 'pet-care-agent-v1';
后续如果新增医疗免责声明、年龄分层喂养或多宠家庭规则,可以升级成 pet-care-agent-v2。
二十三、真机验证流程
真机验证建议按下面步骤:
- 使用与小艺开放平台配置一致的应用包名、签名证书和发布渠道构建应用;
- 在支持小艺智能体能力的 HarmonyOS 真机上安装;
- 登录具备测试权限的华为账号;
- 打开“我的 -> 设置 -> 小艺智能体”;
- 确认本地智能体能回答“新手养宠需要准备什么”;
- 写入
agentId后确认页面状态变为“待链接”; - 写入
launchUri后确认页面状态变为“可测试”; - 点击“打开官网小艺智能体”,验证是否拉起成功;
- 失败时检查应用关联、签名、系统版本、地区和账号测试权限。
这套流程可以给测试同学直接使用。
二十四、本地测试用例
本地智能体可以用轻量断言测试:
const emptyPets: Pet[] = [];
const welcome = XiaoyiPetAgentService.welcome(emptyPets);
assert(welcome.includes('先添加宠物档案'));
const answer = XiaoyiPetAgentService.reply('新手养宠需要准备什么', emptyPets);
assert(answer.includes('基础用品'));
const vaccine = XiaoyiPetAgentService.reply('疫苗记录应该怎么填', emptyPets);
assert(vaccine.includes('接种日期'));
有宠物档案时:
const pets: Pet[] = [mockPetWithoutCareFields()];
const profile = XiaoyiPetAgentService.reply('帮我检查宠物档案还缺哪些照护信息', pets);
assert(profile.includes('疫苗记录'));
assert(profile.includes('驱虫记录'));
assert(profile.includes('饮食习惯'));
匹配不到知识库时:
const fallback = XiaoyiPetAgentService.reply('这个问题暂时不在知识库里', emptyPets);
assert(fallback.includes('宠物档案'));
assert(fallback.includes('知识库'));
二十五、常见问题排查
| 现象 | 可能原因 | 排查方式 |
|---|---|---|
| 页面显示待配置 | agentId 为空 |
检查 XiaoyiAgentConfig.agentId |
| 页面显示待链接 | 只填了 agentId,没填 launchUri |
检查平台启动链接 |
| 点击平台入口失败 | 应用关联、签名、账号或系统版本不满足 | 看 statusText 提示 |
| 快捷问题不显示宠物名 | 当前用户没有宠物档案 | 查 MockStore.petsOf(MockStore.meId) |
| 档案检查没有缺项 | 宠物档案字段都已填写 | 清空一个字段再测试 |
| 通用问答答非所问 | 关键词过宽或分类命中错误 | 调整 keywords 和阈值 |
| 知识库摘要为空 | seed() 没返回记录 |
检查 records 初始化 |
| 平台回答和本地回答不一致 | JSON 知识库没有同步 | 对比 XiaoyiKnowledgeDatabase 和平台导入材料 |
| 页面输入后没清空 | this.draft = '' 没执行 |
检查 ask() |
| 长回答显示拥挤 | 气泡宽度或行高不合理 | 检查 constraintSize 和 lineHeight |
二十六、上线前验收清单
- 未配置
agentId时,本地智能体仍然可用; - 写入
agentId后,页面状态显示待链接; - 写入
launchUri后,页面状态显示可测试; - “刷新档案”能重新读取当前用户宠物档案;
- 没有宠物档案时,欢迎语引导添加档案;
- 有宠物档案时,欢迎语显示档案数量;
- 快捷问题至少包含档案检查、今日提醒、饮食清洁、新手准备、疫苗记录;
- 点击快捷问题能自动追加用户消息和智能体回答;
- 空输入不会发送;
- 发送后输入框清空;
- “新手养宠需要准备什么”命中知识库;
- “疫苗记录应该怎么填”命中知识库;
- “帮我检查宠物档案还缺哪些照护信息”走档案检查逻辑;
- 知识库摘要显示条数和分类;
- 平台拉起失败时给出排查提示;
- 平台侧知识库版本和
XiaoyiAgentConfig.promptVersion保持一致; - 平台导入 JSON 和 App 内置知识库内容保持同步;
- 不要求用户输入身份证号、详细住址、电话等敏感信息;
- 回答不扩展到当前应用以外的业务场景;
- 真机验证覆盖包名、签名、系统版本、账号权限和平台应用关联。
总结
小艺照护助手不是简单加一个聊天页。宠物邻里项目把它拆成了本地智能体、本地知识库、宠物档案上下文和平台入口四层:本地能力保证开发期和未配置平台时仍然可用,知识库保证回答可解释,宠物档案让建议和用户数据相关,平台入口则为后续小艺开放平台接入留下扩展点。
这种分层方式适合大多数 HarmonyOS 应用。先把能验证的本地闭环做好,再把稳定的知识库和提示词同步到平台,最后通过 agentId、launchUri、包名签名和真机账号完成平台拉起验证。这样智能体功能不会停留在演示,而是能真正进入项目的工程质量体系。
更多推荐



所有评论(0)