在这里插入图片描述

📖 引言

HarmonyOS 7引入了强大的AI引擎能力,为应用提供智能推荐、语音交互、图像识别等AI能力。在《趣答》学习应用中,我们可以利用AI引擎实现个性化学习推荐,根据用户的答题历史、兴趣偏好和学习进度,智能推荐最适合的题目和学习路径。

本文将深入探讨如何在HarmonyOS 7中集成AI引擎,为《趣答》应用添加智能推荐和学习辅助功能。

通过本文,你将掌握:

  • HarmonyOS AI引擎的核心能力
  • 如何集成AI引擎SDK
  • 实现个性化题目推荐
  • 智能学习路径规划
  • AI辅助的学习分析

🎯 学习目标

完成本文后,你将能够:

  • ✅ 理解HarmonyOS AI引擎的架构和能力
  • ✅ 配置和初始化AI引擎
  • ✅ 实现基于用户行为的智能推荐
  • ✅ 创建个性化学习路径规划
  • ✅ 集成AI辅助的学习分析功能

💡 需求分析

功能模块设计

模块 功能描述 技术要点
智能推荐引擎 根据用户行为推荐题目 AI引擎、协同过滤、内容推荐
学习路径规划 根据用户水平生成学习路径 知识图谱、难度评估、进度追踪
学习分析报告 AI驱动的学习数据分析 数据挖掘、趋势分析、可视化
智能提示系统 答题时的智能辅助提示 语义分析、上下文理解

🛠️ 核心实现

步骤1: 配置AI引擎依赖

功能说明

在项目中配置AI引擎的依赖包,为后续集成做准备。

完整代码
// entry/oh-package.json5
{
  "name": "@ohos/entry",
  "version": "1.0.0",
  "description": "Entry module for Quda application",
  "main": "",
  "dependencies": {
    "@ohos/aiEngine": "^1.0.0",
    "@ohos/aiModel": "^1.0.0",
    "@ohos/aiNlp": "^1.0.0"
  },
  "devDependencies": {}
}
// build-profile.json5
{
  "apiType": "stageMode",
  "buildOption": {
    "product": "default",
    "arkOptions": {
      "sourceType": "ets",
      "runtimeOS": "HarmonyOS",
      "apiVersion": 26
    }
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "target": "entry",
      "buildOption": {
        "buildMode": "release",
        "externalNativeBuild": {
          "cmake": {
            "path": "entry/src/main/cpp/CMakeLists.txt"
          }
        }
      }
    }
  ]
}
代码解析

1. AI引擎依赖

"dependencies": {
  "@ohos/aiEngine": "^1.0.0",
  "@ohos/aiModel": "^1.0.0",
  "@ohos/aiNlp": "^1.0.0"
}

原理/说明:

  • @ohos/aiEngine: AI引擎核心能力
  • @ohos/aiModel: AI模型管理
  • @ohos/aiNlp: 自然语言处理能力

2. CMake配置

"externalNativeBuild": {
  "cmake": {
    "path": "entry/src/main/cpp/CMakeLists.txt"
  }
}

原理/说明:

  • AI引擎部分功能需要C++支持
  • 配置CMake构建脚本

步骤2: 创建AI引擎服务

功能说明

创建AI引擎服务,封装AI能力的调用接口。

完整代码
// entry/src/main/ets/services/AIEngineService.ts
import { aiEngine } from '@ohos.aiEngine';
import { aiModel } from '@ohos.aiModel';
import { hilog } from '@ohos.hilog';
import { BusinessError } from '@ohos.base';

const TAG = 'AIEngineService';

export interface RecommendationResult {
  questionId: string;
  score: number;
  reason: string;
}

export interface LearningPath {
  levelId: string;
  levelName: string;
  recommendedOrder: number;
  estimatedTime: number;
  difficulty: number;
}

export class AIEngineService {
  private engine: aiEngine.AIEngine | null = null;
  private modelManager: aiModel.ModelManager | null = null;
  private isInitialized: boolean = false;

  async init(): Promise<void> {
    try {
      this.engine = aiEngine.createAIEngine();
      hilog.info(0x0000, TAG, 'AI Engine created successfully');
      
      this.modelManager = aiModel.createModelManager();
      hilog.info(0x0000, TAG, 'Model Manager created successfully');
      
      await this.loadModels();
      this.isInitialized = true;
      hilog.info(0x0000, TAG, 'AI Engine initialized successfully');
    } catch (err) {
      hilog.error(0x0000, TAG, 'Failed to initialize AI engine: %{public}s', 
        JSON.stringify(err));
    }
  }

  private async loadModels(): Promise<void> {
    try {
      const modelInfo: aiModel.ModelInfo = {
        modelName: 'recommendation_model',
        modelType: aiModel.ModelType.LOCAL,
        modelPath: 'assets/recommendation_model.om',
        version: '1.0.0'
      };
      
      await this.modelManager!.loadModel(modelInfo);
      hilog.info(0x0000, TAG, 'Recommendation model loaded successfully');
      
      const nlpModelInfo: aiModel.ModelInfo = {
        modelName: 'nlp_model',
        modelType: aiModel.ModelType.LOCAL,
        modelPath: 'assets/nlp_model.om',
        version: '1.0.0'
      };
      
      await this.modelManager!.loadModel(nlpModelInfo);
      hilog.info(0x0000, TAG, 'NLP model loaded successfully');
    } catch (err) {
      hilog.error(0x0000, TAG, 'Failed to load models: %{public}s', JSON.stringify(err));
    }
  }

  async getRecommendations(
    userId: string,
    userHistory: Array<{ questionId: string; isCorrect: boolean; timestamp: number }>,
    preferences: Array<string>,
    count: number = 10
  ): Promise<RecommendationResult[]> {
    if (!this.isInitialized || !this.engine) {
      return this.getFallbackRecommendations(userHistory, preferences, count);
    }

    try {
      const input: aiEngine.AIInput = {
        userId: userId,
        history: userHistory,
        preferences: preferences,
        count: count,
        context: {
          timestamp: Date.now(),
          deviceType: 'phone'
        }
      };

      const output = await this.engine!.run('recommendation', input);
      
      if (output && output.results) {
        return output.results.map((item: any) => ({
          questionId: item.questionId,
          score: item.score,
          reason: item.reason || '基于您的学习历史推荐'
        }));
      }
      
      return this.getFallbackRecommendations(userHistory, preferences, count);
    } catch (err) {
      hilog.error(0x0000, TAG, 'Failed to get recommendations: %{public}s', 
        JSON.stringify(err));
      return this.getFallbackRecommendations(userHistory, preferences, count);
    }
  }

  private getFallbackRecommendations(
    userHistory: Array<{ questionId: string; isCorrect: boolean; timestamp: number }>,
    preferences: Array<string>,
    count: number
  ): RecommendationResult[] {
    const results: RecommendationResult[] = [];
    const wrongQuestions = userHistory.filter(h => !h.isCorrect).map(h => h.questionId);
    
    for (let i = 0; i < count; i++) {
      const questionId = `question_${Date.now()}_${i}`;
      const reason = wrongQuestions.length > 0 && i < wrongQuestions.length 
        ? '错题复习推荐' 
        : '综合推荐';
      
      results.push({
        questionId: questionId,
        score: Math.random() * 0.5 + 0.5,
        reason: reason
      });
    }
    
    return results;
  }

  async generateLearningPath(
    userId: string,
    currentLevel: number,
    scoreHistory: Array<{ date: number; score: number; level: number }>
  ): Promise<LearningPath[]> {
    if (!this.isInitialized || !this.engine) {
      return this.getFallbackLearningPath(currentLevel);
    }

    try {
      const input: aiEngine.AIInput = {
        userId: userId,
        currentLevel: currentLevel,
        scoreHistory: scoreHistory,
        targetLevel: 10
      };

      const output = await this.engine!.run('learning_path', input);
      
      if (output && output.path) {
        return output.path.map((item: any, index: number) => ({
          levelId: item.levelId,
          levelName: item.levelName,
          recommendedOrder: index + 1,
          estimatedTime: item.estimatedTime,
          difficulty: item.difficulty
        }));
      }
      
      return this.getFallbackLearningPath(currentLevel);
    } catch (err) {
      hilog.error(0x0000, TAG, 'Failed to generate learning path: %{public}s', 
        JSON.stringify(err));
      return this.getFallbackLearningPath(currentLevel);
    }
  }

  private getFallbackLearningPath(currentLevel: number): LearningPath[] {
    const path: LearningPath[] = [];
    const levelNames = ['入门篇', '基础篇', '进阶篇', '高级篇', '专家篇'];
    
    for (let i = currentLevel; i < Math.min(currentLevel + 5, 10); i++) {
      path.push({
        levelId: `level_${i}`,
        levelName: levelNames[i % levelNames.length],
        recommendedOrder: i - currentLevel + 1,
        estimatedTime: 30 + i * 10,
        difficulty: i * 10
      });
    }
    
    return path;
  }

  async analyzeLearningPatterns(
    userId: string,
    studyRecords: Array<{ startTime: number; endTime: number; score: number }>
  ): Promise<{
    bestTimeOfDay: string;
    averageStudyDuration: number;
    improvementRate: number;
    suggestedFrequency: number;
  }> {
    if (!studyRecords || studyRecords.length === 0) {
      return {
        bestTimeOfDay: '暂无数据',
        averageStudyDuration: 0,
        improvementRate: 0,
        suggestedFrequency: 5
      };
    }

    try {
      const hourlyData: Record<number, { count: number; totalScore: number }> = {};
      let totalDuration = 0;
      let firstScore = studyRecords[0].score;
      let lastScore = studyRecords[studyRecords.length - 1].score;

      studyRecords.forEach(record => {
        const hour = new Date(record.startTime).getHours();
        if (!hourlyData[hour]) {
          hourlyData[hour] = { count: 0, totalScore: 0 };
        }
        hourlyData[hour].count++;
        hourlyData[hour].totalScore += record.score;
        
        totalDuration += record.endTime - record.startTime;
      });

      let bestHour = 0;
      let bestAvgScore = 0;
      Object.keys(hourlyData).forEach(hour => {
        const avgScore = hourlyData[parseInt(hour)].totalScore / hourlyData[parseInt(hour)].count;
        if (avgScore > bestAvgScore) {
          bestAvgScore = avgScore;
          bestHour = parseInt(hour);
        }
      });

      const improvementRate = firstScore > 0 
        ? Math.round(((lastScore - firstScore) / firstScore) * 100) 
        : 0;

      return {
        bestTimeOfDay: `${bestHour}:00 - ${bestHour + 1}:00`,
        averageStudyDuration: Math.round(totalDuration / studyRecords.length / 60000),
        improvementRate: improvementRate,
        suggestedFrequency: Math.min(7, Math.round(studyRecords.length / 7) + 1)
      };
    } catch (err) {
      hilog.error(0x0000, TAG, 'Failed to analyze learning patterns: %{public}s', 
        JSON.stringify(err));
      return {
        bestTimeOfDay: '暂无数据',
        averageStudyDuration: 0,
        improvementRate: 0,
        suggestedFrequency: 5
      };
    }
  }

  async getSmartHint(questionId: string, userAnswers: Array<number>): Promise<string> {
    if (!this.isInitialized || !this.engine) {
      return '仔细阅读题目,回忆相关知识点';
    }

    try {
      const input: aiEngine.AIInput = {
        questionId: questionId,
        userAnswers: userAnswers,
        hintType: 'concept'
      };

      const output = await this.engine!.run('hint', input);
      
      if (output && output.hint) {
        return output.hint;
      }
      
      return '仔细阅读题目,回忆相关知识点';
    } catch (err) {
      hilog.error(0x0000, TAG, 'Failed to get smart hint: %{public}s', JSON.stringify(err));
      return '仔细阅读题目,回忆相关知识点';
    }
  }

  destroy(): void {
    if (this.modelManager) {
      this.modelManager.unloadModel('recommendation_model');
      this.modelManager.unloadModel('nlp_model');
    }
    this.isInitialized = false;
    hilog.info(0x0000, TAG, 'AI Engine service destroyed');
  }
}
代码解析

1. AI引擎初始化

async init(): Promise<void> {
  this.engine = aiEngine.createAIEngine();
  this.modelManager = aiModel.createModelManager();
  await this.loadModels();
}

原理/说明:

  • 创建AI引擎实例
  • 创建模型管理器
  • 加载本地AI模型

2. 智能推荐

async getRecommendations(userId, userHistory, preferences, count) {
  const input: aiEngine.AIInput = {
    userId,
    history: userHistory,
    preferences,
    count,
    context: { timestamp: Date.now(), deviceType: 'phone' }
  };
  const output = await this.engine!.run('recommendation', input);
}

原理/说明:

  • 构建推荐输入数据
  • 调用AI引擎的推荐能力
  • 返回推荐结果和置信度

3. 学习路径生成

async generateLearningPath(userId, currentLevel, scoreHistory) {
  const input: aiEngine.AIInput = {
    userId,
    currentLevel,
    scoreHistory,
    targetLevel: 10
  };
  const output = await this.engine!.run('learning_path', input);
}

原理/说明:

  • 基于用户当前水平和历史成绩
  • 生成个性化学习路径
  • 包含预估时间和难度评估

步骤3: 创建智能推荐页面

功能说明

创建智能推荐页面,展示AI推荐的题目列表。

完整代码
// entry/src/main/ets/pages/SmartRecommend.ets
import { AIEngineService, RecommendationResult } from '../services/AIEngineService';
import { QuizService } from '../services/QuizService';
import router from '@ohos.router';

@Entry
@Component
struct SmartRecommend {
  @State recommendations: RecommendationResult[] = [];
  @State questions: Array<any> = [];
  @State isLoading: boolean = true;
  @State refreshTrigger: number = 0;

  private aiEngineService: AIEngineService = new AIEngineService();
  private quizService: QuizService = new QuizService();

  build() {
    Column() {
      if (this.isLoading) {
        this.buildLoading();
      } else {
        this.buildContent();
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
    .onAppear(() => {
      this.loadRecommendations();
    })
  }

  buildLoading() {
    return Column() {
      LoadingProgress()
        .width(40)
        .height(40)
        .color('#007DFF')
      Text('AI正在为您推荐题目...')
        .fontSize(16)
        .fontColor('#666666')
        .margin({ top: 16 })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  buildContent() {
    return Column() {
      Row() {
        Text('智能推荐')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .fontColor('#333333')
        Button('刷新')
          .width(60)
          .height(32)
          .borderRadius(6)
          .backgroundColor('#007DFF')
          .fontColor('#FFFFFF')
          .fontSize(12)
          .margin({ left: 'auto' })
          .onClick(() => {
            this.refreshRecommendations();
          })
      }
      .width('100%')
      .padding(20)

      Text('基于您的学习历史和兴趣偏好,AI为您推荐以下题目')
        .fontSize(14)
        .fontColor('#666666')
        .padding({ left: 20, right: 20, bottom: 16 })

      List() {
        ForEach(this.questions, (question: any, index: number) => {
          ListItem() {
            this.buildQuestionCard(question, index)
          }
          .margin({ bottom: 12 })
        })
      }
      .width('100%')
      .padding({ left: 20, right: 20 })
      .divider({ strokeWidth: 0 })
    }
  }

  buildQuestionCard(question: any, index: number) {
    const recommendation = this.recommendations[index];
    
    return Column() {
      Row() {
        Text(`推荐度: ${Math.round((recommendation?.score || 0) * 100)}%`)
          .fontSize(12)
          .fontColor('#00C853')
          .backgroundColor('#E8F5E9')
          .padding({ left: 8, right: 8, top: 4, bottom: 4 })
          .borderRadius(4)
        Text(recommendation?.reason || '')
          .fontSize(12)
          .fontColor('#999999')
          .margin({ left: 8 })
      }
      .margin({ bottom: 8 })

      Text(question.question)
        .fontSize(16)
        .fontColor('#333333')
        .margin({ bottom: 12 })

      Row() {
        Text(question.subject)
          .fontSize(12)
          .fontColor('#666666')
        Text(`难度: ${'★'.repeat(question.difficulty)}${'☆'.repeat(5 - question.difficulty)}`)
          .fontSize(12)
          .fontColor('#FFB74D')
          .margin({ left: 'auto' })
      }

      Button('开始答题')
        .width('100%')
        .height(44)
        .borderRadius(8)
        .backgroundColor('#007DFF')
        .fontColor('#FFFFFF')
        .margin({ top: 12 })
        .onClick(() => {
          router.pushUrl({
            url: 'pages/Quiz',
            params: { questionId: question.id }
          });
        })
    }
    .width('100%')
    .padding(16)
    .backgroundColor('#FFFFFF')
    .borderRadius(12)
  }

  async loadRecommendations() {
    this.isLoading = true;
    
    try {
      await this.aiEngineService.init();
      
      const mockHistory = [
        { questionId: 'q1', isCorrect: true, timestamp: Date.now() - 86400000 },
        { questionId: 'q2', isCorrect: false, timestamp: Date.now() - 86400000 },
        { questionId: 'q3', isCorrect: true, timestamp: Date.now() - 172800000 }
      ];
      
      const preferences = ['history', 'science'];
      
      this.recommendations = await this.aiEngineService.getRecommendations(
        'user_001',
        mockHistory,
        preferences,
        5
      );
      
      const questionIds = this.recommendations.map(r => r.questionId);
      this.questions = await this.quizService.getQuestionsByIds(questionIds);
      
      if (this.questions.length === 0) {
        this.questions = await this.quizService.getRandomQuestions(5);
      }
    } catch (err) {
      this.questions = await this.quizService.getRandomQuestions(5);
    } finally {
      this.isLoading = false;
    }
  }

  async refreshRecommendations() {
    this.refreshTrigger++;
    await this.loadRecommendations();
  }
}
代码解析

1. 推荐度展示

Text(`推荐度: ${Math.round((recommendation?.score || 0) * 100)}%`)
  .fontSize(12)
  .fontColor('#00C853')
  .backgroundColor('#E8F5E9')

原理/说明:

  • 显示AI推荐的置信度分数
  • 使用绿色背景突出显示

2. 动态加载推荐题目

async loadRecommendations() {
  await this.aiEngineService.init();
  this.recommendations = await this.aiEngineService.getRecommendations(...);
  const questionIds = this.recommendations.map(r => r.questionId);
  this.questions = await this.quizService.getQuestionsByIds(questionIds);
}

原理/说明:

  • 初始化AI引擎
  • 获取推荐结果
  • 根据推荐的questionId加载题目详情

步骤4: 创建学习路径规划页面

功能说明

创建学习路径规划页面,展示AI生成的个性化学习路径。

完整代码
// entry/src/main/ets/pages/LearningPathAI.ets
import { AIEngineService, LearningPath } from '../services/AIEngineService';
import router from '@ohos.router';

@Entry
@Component
struct LearningPathAI {
  @State learningPath: LearningPath[] = [];
  @State currentLevel: number = 1;
  @State isLoading: boolean = true;

  private aiEngineService: AIEngineService = new AIEngineService();

  build() {
    Column() {
      if (this.isLoading) {
        Column() {
          LoadingProgress()
            .width(40)
            .height(40)
            .color('#007DFF')
          Text('AI正在规划学习路径...')
            .fontSize(16)
            .fontColor('#666666')
            .margin({ top: 16 })
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
      } else {
        this.buildContent();
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
    .onAppear(() => {
      this.loadLearningPath();
    })
  }

  buildContent() {
    return Column() {
      Text('AI学习路径规划')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .margin({ bottom: 20 })
        .padding({ top: 20, left: 20 })

      Text(`当前等级: ${this.currentLevel}`)
        .fontSize(16)
        .fontColor('#007DFF')
        .margin({ bottom: 20 })
        .padding({ left: 20 })

      Column() {
        ForEach(this.learningPath, (path: LearningPath, index: number) => {
          Column() {
            if (index > 0) {
              Row() {
                Line()
                  .width(1)
                  .height(20)
                  .strokeColor('#DDDDDD')
              }
              .width('100%')
              .justifyContent(FlexAlign.Center)
            }

            Row() {
              Stack() {
                Circle()
                  .width(40)
                  .height(40)
                  .fill(index === 0 ? '#007DFF' : '#FFFFFF')
                  .stroke(index === 0 ? '#007DFF' : '#DDDDDD')
                  .strokeWidth(2)
                Text(`${path.recommendedOrder}`)
                  .fontSize(14)
                  .fontColor(index === 0 ? '#FFFFFF' : '#666666')
              }

              Column() {
                Text(path.levelName)
                  .fontSize(16)
                  .fontColor('#333333')
                  .fontWeight(FontWeight.Medium)
                Text(`预估时间: ${path.estimatedTime}分钟 | 难度: ${path.difficulty}%`)
                  .fontSize(12)
                  .fontColor('#999999')
              }
              .margin({ left: 16 })
              .flexGrow(1)

              Button(index === 0 ? '开始学习' : '查看详情')
                .width(80)
                .height(36)
                .borderRadius(6)
                .backgroundColor(index === 0 ? '#007DFF' : '#EEEEEE')
                .fontColor(index === 0 ? '#FFFFFF' : '#333333')
                .fontSize(12)
                .onClick(() => {
                  this.navigateToLevel(path.levelId);
                })
            }
            .width('100%')
            .padding({ left: 20, right: 20, top: 12, bottom: 12 })
          }
        })
      }

      Text('AI将根据您的学习进度动态调整路径')
        .fontSize(14)
        .fontColor('#999999')
        .margin({ top: 20 })
        .textAlign(TextAlign.Center)
    }
  }

  async loadLearningPath() {
    this.isLoading = true;
    
    try {
      await this.aiEngineService.init();
      
      const mockScoreHistory = [
        { date: Date.now() - 604800000, score: 60, level: 1 },
        { date: Date.now() - 518400000, score: 75, level: 1 },
        { date: Date.now() - 432000000, score: 80, level: 2 },
        { date: Date.now() - 345600000, score: 85, level: 2 },
        { date: Date.now() - 259200000, score: 90, level: 2 }
      ];
      
      this.learningPath = await this.aiEngineService.generateLearningPath(
        'user_001',
        this.currentLevel,
        mockScoreHistory
      );
    } catch (err) {
      this.learningPath = this.aiEngineService.generateLearningPath(
        'user_001',
        this.currentLevel,
        []
      ) as LearningPath[];
    } finally {
      this.isLoading = false;
    }
  }

  navigateToLevel(levelId: string) {
    router.pushUrl({
      url: 'pages/LevelDetail',
      params: { levelId: levelId }
    });
  }
}
代码解析

1. 路径可视化

Stack() {
  Circle()
    .width(40)
    .height(40)
    .fill(index === 0 ? '#007DFF' : '#FFFFFF')
    .stroke(index === 0 ? '#007DFF' : '#DDDDDD')
    .strokeWidth(2)
  Text(`${path.recommendedOrder}`)
    .fontSize(14)
    .fontColor(index === 0 ? '#FFFFFF' : '#666666')
}

原理/说明:

  • 当前学习节点用蓝色填充
  • 其他节点用白色填充、灰色边框
  • 显示推荐顺序编号

2. 连接线

if (index > 0) {
  Row() {
    Line()
      .width(1)
      .height(20)
      .strokeColor('#DDDDDD')
  }
  .width('100%')
  .justifyContent(FlexAlign.Center)
}

原理/说明:

  • 在节点之间添加连接线
  • 使用灰色线条表示学习路径

步骤5: 创建AI学习分析报告页面

功能说明

创建AI学习分析报告页面,展示用户的学习模式分析结果。

完整代码
// entry/src/main/ets/pages/AnalyticsReportAI.ets
import { AIEngineService } from '../services/AIEngineService';

@Entry
@Component
struct AnalyticsReportAI {
  @State analysis: {
    bestTimeOfDay: string;
    averageStudyDuration: number;
    improvementRate: number;
    suggestedFrequency: number;
  } = {
    bestTimeOfDay: '暂无数据',
    averageStudyDuration: 0,
    improvementRate: 0,
    suggestedFrequency: 5
  };
  @State isLoading: boolean = true;

  private aiEngineService: AIEngineService = new AIEngineService();

  build() {
    Column() {
      if (this.isLoading) {
        Column() {
          LoadingProgress()
            .width(40)
            .height(40)
            .color('#007DFF')
          Text('AI正在分析学习数据...')
            .fontSize(16)
            .fontColor('#666666')
            .margin({ top: 16 })
        }
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
      } else {
        this.buildContent();
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
    .onAppear(() => {
      this.loadAnalysis();
    })
  }

  buildContent() {
    return Column() {
      Text('AI学习分析报告')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .margin({ bottom: 20 })
        .padding({ top: 20, left: 20 })

      this.buildStatCard(
        '最佳学习时间',
        this.analysis.bestTimeOfDay,
        '根据您的学习记录分析得出',
        '⏰'
      )

      this.buildStatCard(
        '平均学习时长',
        `${this.analysis.averageStudyDuration}分钟`,
        '单次学习的平均时长',
        '⏱️'
      )

      this.buildStatCard(
        '进步率',
        `${this.analysis.improvementRate > 0 ? '+' : ''}${this.analysis.improvementRate}%`,
        '近期成绩相比初始成绩的变化',
        '📈',
        this.analysis.improvementRate >= 0 ? '#00C853' : '#FF5252'
      )

      this.buildStatCard(
        '建议学习频率',
        `${this.analysis.suggestedFrequency}天/周`,
        'AI建议的最佳学习频率',
        '📅'
      )

      Column() {
        Text('学习建议')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .fontColor('#333333')
          .margin({ bottom: 16 })

        Column() {
          Text(`1. 建议在${this.analysis.bestTimeOfDay}进行学习,此时您的学习效率最高`)
            .fontSize(14)
            .fontColor('#666666')
            .margin({ bottom: 8 })

          Text(`2. 保持每周${this.analysis.suggestedFrequency}天的学习频率,效果最佳`)
            .fontSize(14)
            .fontColor('#666666')
            .margin({ bottom: 8 })

          Text('3. 每次学习建议保持20-30分钟,避免疲劳')
            .fontSize(14)
            .fontColor('#666666')
            .margin({ bottom: 8 })

          Text('4. 定期复习错题,巩固薄弱知识点')
            .fontSize(14)
            .fontColor('#666666')
        }
      }
      .width('100%')
      .padding(20)
      .backgroundColor('#FFFFFF')
      .borderRadius(12)
      .margin({ top: 16, left: 20, right: 20 })
    }
  }

  buildStatCard(
    title: string,
    value: string,
    description: string,
    icon: string,
    valueColor: string = '#007DFF'
  ) {
    return Row() {
      Column() {
        Text(icon)
          .fontSize(28)
        }
        .width(60)
        .height(60)
        .backgroundColor('#E3F2FD')
        .borderRadius(12)
        .justifyContent(FlexAlign.Center)
        .margin({ right: 16 })

      Column() {
        Text(title)
          .fontSize(14)
          .fontColor('#666666')
          .margin({ bottom: 4 })
        Text(value)
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .fontColor(valueColor)
          .margin({ bottom: 4 })
        Text(description)
          .fontSize(12)
          .fontColor('#999999')
      }
      .flexGrow(1)
    }
    .width('100%')
    .padding(20)
    .backgroundColor('#FFFFFF')
    .borderRadius(12)
    .margin({ left: 20, right: 20, bottom: 12 })
  }

  async loadAnalysis() {
    this.isLoading = true;
    
    try {
      await this.aiEngineService.init();
      
      const mockStudyRecords = [
        { startTime: Date.now() - 86400000 * 7 + 3600000 * 20, endTime: Date.now() - 86400000 * 7 + 3600000 * 21, score: 60 },
        { startTime: Date.now() - 86400000 * 6 + 3600000 * 20, endTime: Date.now() - 86400000 * 6 + 3600000 * 21.5, score: 70 },
        { startTime: Date.now() - 86400000 * 5 + 3600000 * 20, endTime: Date.now() - 86400000 * 5 + 3600000 * 21, score: 75 },
        { startTime: Date.now() - 86400000 * 4 + 3600000 * 20, endTime: Date.now() - 86400000 * 4 + 3600000 * 22, score: 80 },
        { startTime: Date.now() - 86400000 * 3 + 3600000 * 20, endTime: Date.now() - 86400000 * 3 + 3600000 * 21, score: 85 },
        { startTime: Date.now() - 86400000 * 2 + 3600000 * 20, endTime: Date.now() - 86400000 * 2 + 3600000 * 21.5, score: 88 },
        { startTime: Date.now() - 86400000 + 3600000 * 20, endTime: Date.now() - 86400000 + 3600000 * 22, score: 90 }
      ];
      
      this.analysis = await this.aiEngineService.analyzeLearningPatterns(
        'user_001',
        mockStudyRecords
      );
    } catch (err) {
      console.error('Failed to load analysis:', err);
    } finally {
      this.isLoading = false;
    }
  }
}
代码解析

1. 统计卡片组件

buildStatCard(title, value, description, icon, valueColor = '#007DFF') {
  return Row() {
    Column() {
      Text(icon).fontSize(28)
    }
    .width(60).height(60)
    .backgroundColor('#E3F2FD')
    .borderRadius(12)
    
    Column() {
      Text(title).fontSize(14).fontColor('#666666')
      Text(value).fontSize(24).fontWeight(FontWeight.Bold).fontColor(valueColor)
      Text(description).fontSize(12).fontColor('#999999')
    }
  }
}

原理/说明:

  • 左侧图标区域
  • 右侧标题、数值、描述
  • 可自定义数值颜色

2. 学习建议生成

Text(`1. 建议在${this.analysis.bestTimeOfDay}进行学习`)
Text(`2. 保持每周${this.analysis.suggestedFrequency}天的学习频率`)

原理/说明:

  • 根据AI分析结果生成个性化建议
  • 建议内容动态生成

⚠️ 常见问题与解决方案

问题1: AI引擎初始化失败

现象:
AI引擎无法初始化,控制台报错"Engine not available"。

原因:

  • 设备不支持AI引擎
  • AI引擎版本不匹配
  • 缺少必要的系统权限

错误代码:

// ❌ 错误: 未检查引擎可用性
this.engine = aiEngine.createAIEngine();

正确代码:

// ✅ 正确: 添加错误处理和降级策略
try {
  this.engine = aiEngine.createAIEngine();
} catch (err) {
  hilog.error(0x0000, TAG, 'AI engine not available, using fallback');
}

规则/建议:

  • 始终添加try-catch处理
  • 实现降级策略(使用规则引擎替代)
  • 检查设备兼容性

问题2: 推荐结果为空

现象:
调用推荐接口后返回空数组。

原因:

  • 用户历史数据不足
  • AI模型未正确加载
  • 输入参数格式错误

错误代码:

// ❌ 错误: 传入空的历史数据
const recommendations = await aiEngine.getRecommendations(userId, [], []);

正确代码:

// ✅ 正确: 确保有足够的历史数据
if (userHistory.length < 3) {
  return this.getFallbackRecommendations();
}
const recommendations = await aiEngine.getRecommendations(userId, userHistory, preferences);

规则/建议:

  • 确保用户有足够的历史数据
  • 实现fallback推荐策略
  • 验证输入参数格式

问题3: AI模型加载失败

现象:
模型加载失败,控制台报错"Model not found"。

原因:

  • 模型文件路径错误
  • 模型文件不存在
  • 模型格式不支持

错误代码:

// ❌ 错误: 路径错误
modelPath: 'models/recommendation_model.om'

正确代码:

// ✅ 正确: 使用正确的assets路径
modelPath: 'assets/recommendation_model.om'

规则/建议:

  • 将模型文件放置在assets目录
  • 确保模型格式为.om
  • 检查模型版本兼容性

问题4: 学习分析结果不准确

现象:
AI分析的学习模式与实际情况不符。

原因:

  • 数据样本不足
  • 数据质量差
  • 算法参数不合适

错误代码:

// ❌ 错误: 使用不完整的数据
const analysis = await aiEngine.analyzeLearningPatterns(userId, lastThreeRecords);

正确代码:

// ✅ 正确: 使用足够的数据样本
if (studyRecords.length < 7) {
  return { /* 默认分析结果 */ };
}
const analysis = await aiEngine.analyzeLearningPatterns(userId, studyRecords);

规则/建议:

  • 收集至少一周的数据再进行分析
  • 过滤异常数据(如学习时长过短)
  • 定期重新训练模型

问题5: AI提示功能响应慢

现象:
调用智能提示接口时响应时间过长。

原因:

  • AI模型推理耗时
  • 网络请求延迟
  • 线程阻塞

错误代码:

// ❌ 错误: 主线程同步调用
const hint = await aiEngine.getSmartHint(questionId, userAnswers);

正确代码:

// ✅ 正确: 使用异步调用并显示加载状态
this.isLoadingHint = true;
aiEngine.getSmartHint(questionId, userAnswers)
  .then(hint => {
    this.hint = hint;
    this.isLoadingHint = false;
  })
  .catch(() => {
    this.hint = '默认提示';
    this.isLoadingHint = false;
  });

规则/建议:

  • 使用异步调用
  • 显示加载状态
  • 设置合理的超时时间

📝 本章小结

核心知识点

本文详细讲解了HarmonyOS 7 AI引擎的集成与应用,主要包括:

1. AI引擎配置

  • 添加AI引擎依赖包
  • 配置CMake构建脚本
  • 加载本地AI模型

2. 智能推荐

  • 基于用户行为的协同过滤
  • 内容推荐算法
  • 推荐结果的置信度评估

3. 学习路径规划

  • 根据用户水平生成路径
  • 知识图谱应用
  • 难度评估和时间预估

4. 学习分析

  • 学习模式识别
  • 最佳学习时间分析
  • 进步率计算

最佳实践总结

AI引擎初始化

try {
  this.engine = aiEngine.createAIEngine();
  await this.loadModels();
} catch (err) {
  // 使用降级策略
}

推荐接口调用

if (userHistory.length < 3) {
  return this.getFallbackRecommendations();
}
const recommendations = await aiEngine.getRecommendations(...);

异步处理

aiEngine.getSmartHint(questionId, userAnswers)
  .then(hint => { this.hint = hint; })
  .catch(() => { this.hint = '默认提示'; });

数据质量保障

if (studyRecords.length < 7) {
  return { /* 默认结果 */ };
}

下一步预告

在下一篇文章中,我们将:

  • 🎨 声明式UI新特性:状态管理与动画升级
  • 🚀 探索HarmonyOS 7的UI性能优化
  • ✨ 实现更流畅的动画效果

🔗 相关链接


💡 提示: 建议结合项目源码阅读,动手实践效果更好!

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐