AI眼鏡Rokid記賬本實戰開發 - 每日花費智能彙總應用

作者:kevin賀老師

一、實戰應用思路

1.1應用概述

基於Rokid AI眼鏡的智能記賬本應用是一個革命性的財務管理系統,通過語音識別、圖像識別和AI智能分析,實現每日花費的自動記錄、智能分類和晚間彙總分析。該應用充分利用了rokid眼鏡的攝像頭、麥克風、觸控板和揚聲器等硬件特性,打造了全新的免手操作的記賬體驗。 image.png

1.2 核心功能架構

  1. 實時消費記錄 - 通過語音或拍照快速記錄消費
  2. 智能識別分類 - AI自動識別商户、商品並進行分類
  3. 晚間財務彙總 - 每日消費統計和分析報告
  4. 多端協同 - 手機端管理,眼鏡端快速操作

1.3 AI工作流設計

核心工作流程

graph TD
    A[用户消費] --> B{記錄方式選擇}
    B -->|語音| C[語音輸入]
    B -->|拍照| D[拍照識別]
    C --> E[ASR語音轉文字]
    D --> F[OCR圖像識別]
    E --> G[AI語義分析]
    F --> G
    G --> H[自動分類]
    H --> I[存儲到本地]
    I --> J[同步到雲端]
    J --> K[晚間彙總分析]

二、AI處理流程詳解

1. 語音記錄工作流
// AI語音識別處理流程
fun handleVoiceRecording() {
    // 1. 監聽眼鏡端AI事件
    setAiEventListener(true)

    // 2. 獲取ASR語音識別結果
    val asrContent = getAsrResult()
    if (asrContent.isNotEmpty()) {
        sendAsrContent(asrContent)
        processVoiceInput(asrContent)
    } else {
        notifyAsrNone()
    }
}

fun processVoiceInput(content: String) {
    // 3. AI語義分析 - 提取金額、商户、類別
    val expenseData = aiAnalysis.analyzeExpenseText(content)

    // 4. 自動分類存儲
    saveExpenseRecord(expenseData)

    // 5. TTS語音反饋
    val feedback = "已記錄${expenseData.amount}元${expenseData.category}"
    sendTTSContent(feedback)
    notifyTtsAudioFinished()
}
2. 拍照識別工作流
// 圖像識別處理流程
fun handleReceiptCapture() {
    // 1. 打開眼鏡相機
    aiOpenCamera(1920, 1080, 80)

    // 2. 拍攝小票/發票
    takePhoto(1920, 1080, 80) { status, photoData ->
        when (status) {
            ValueUtil.CxrStatus.RESPONSE_SUCCEED -> {
                // 3. OCR圖像識別
                val ocrResult = ocrService.recognizeReceipt(photoData)

                // 4. AI信息提取
                val expenseInfo = aiService.extractExpenseInfo(ocrResult)

                // 5. 智能分類
                val category = aiService.categorizeExpense(expenseInfo)

                // 6. 保存記錄
                saveExpenseRecord(expenseInfo.copy(category = category))

                // 7. 語音確認
                sendTTSContent("識別到消費:${expenseInfo.amount}元,${category}")
            }
            else -> notifyPicUploadError()
        }
    }
}

三、 純眼鏡端應用開發

3.1 提詞器場景實現

利用提詞器API實現智能引導和操作提示:

class GlassesTeleprompterService {
    private val TAG = "TeleprompterService"

    /**
     * 初始化記賬引導場景
     */
    fun initAccountingGuidance() {
        // 開啓提詞器場景
        val openStatus = openOrCloseWordTips(true)
        when (openStatus) {
            ValueUtil.CxrStatus.REQUEST_SUCCEED -> {
                // 設置引導內容
                setGuidanceContent()
                // 配置顯示參數
                configureDisplay()
            }
            ValueUtil.CxrStatus.REQUEST_WAITING -> {
                Log.d(TAG, "請求等待中,請稍後再試")
            }
            ValueUtil.CxrStatus.REQUEST_FAILED -> {
                Log.e(TAG, "打開提詞器失敗")
            }
        }
    }

    /**
     * 設置引導內容
     */
    private fun setGuidanceContent() {
        val guidanceText = """
            智能記賬助手

            歡迎使用AI記賬本

            記錄方式:
            • 語音:"記錄消費50元午餐"
            • 拍照:拍攝小票/發票

             操作提示:
            • 輕觸觸控板:開始語音記錄
            • 按拍照鍵:拍攝收據

            每日晚8點自動彙總

            開始記賬 →
        """.trimIndent()

        val status = setWordTipsText(guidanceText, "accounting_guidance.txt")
        Log.d(TAG, "設置引導內容狀態: $status")
    }

    /**
     * 配置顯示參數
     */
    private fun configureDisplay() {
        val configStatus = configWordTipsText(
            textSize = 32f,      // 字體大小
            lineSpace = 1.5f,    // 行間距
            mode = "ai",         // AI模式,支持ASR觸發行滑動
            startPointX = 100,   // X座標
            startPointY = 200,   // Y座標
            width = 800,         // 寬度
            height = 600         // 高度
        )
        Log.d(TAG, "配置顯示參數狀態: $configStatus")
    }

    /**
     * AI模式ASR內容處理
     */
    fun handleAsrForTeleprompter(content: String) {
        // 發送ASR內容到提詞器,實現智能滾動
        val status = sendWordTipsAsrContent(content)
        Log.d(TAG, "ASR內容發送狀態: $status")
    }

    /**
     * 關閉引導場景
     */
    fun closeGuidance() {
        val closeStatus = openOrCloseWordTips(false)
        Log.d(TAG, "關閉提詞器狀態: $closeStatus")
    }
}

3.2AI場景事件監聽

class GlassesAISceneController {
    private val aiEventListener = object : AiEventListener {

        override fun onAiKeyDown() {
            Log.d("AI_SCENE", "AI按鍵按下 - 開始語音記錄")
            startVoiceRecording()
        }

        override fun onAiKeyUp() {
            Log.d("AI_SCENE", "AI按鍵釋放")
            // 可以在這裏處理按鍵釋放邏輯
        }

        override fun onAiExit() {
            Log.d("AI_SCENE", "AI場景退出")
            // 清理資源,保存當前狀態
            cleanupResources()
        }
    }

    /**
     * 開始語音記錄
     */
    private fun startVoiceRecording() {
        // 啓動ASR識別
        asrService.startListening()

        // 發送ASR內容到提詞器用於AI模式
        teleprompterService.handleAsrForTeleprompter("正在識別語音...")
    }

    /**
     * 設置AI事件監聽
     */
    fun setAiEventListener() {
        CxrApi.getInstance().setAiEventListener(aiEventListener)
    }

    /**
     * 移除AI事件監聽
     */
    fun removeAiEventListener() {
        CxrApi.getInstance().setAiEventListener(null)
    }
}

3.3 純手機端應用配合眼鏡

a、主Activity設計

class MainActivity : AppCompatActivity() {
    private lateinit var glassesConnectionManager: GlassesConnectionManager
    private lateinit var expenseManager: ExpenseManager
    private lateinit var dailySummaryManager: DailySummaryManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化組件
        initComponents()

        // 設置眼鏡連接
        setupGlassesConnection()

        // 啓動晚間彙總定時任務
        scheduleDailySummary()
    }

    private fun initComponents() {
        glassesConnectionManager = GlassesConnectionManager(this)
        expenseManager = ExpenseManager(this)
        dailySummaryManager = DailySummaryManager(this)
    }

    private fun setupGlassesConnection() {
        // 檢查眼鏡連接狀態
        if (glassesConnectionManager.isConnected()) {
            // 連接眼鏡成功,發送歡迎信息
            sendWelcomeMessage()
            // 啓動眼鏡端AI場景
            startGlassesAIScene()
        } else {
            // 顯示連接提示
            showConnectionPrompt()
        }
    }
}

b、眼鏡連接管理器

class GlassesConnectionManager(private val context: Context) {
    private val TAG = "GlassesConnection"

    /**
     * 檢查眼鏡連接狀態
     */
    fun isConnected(): Boolean {
        // 實現眼鏡連接檢測邏輯
        return true // 模擬連接成功
    }

    /**
     * 發送歡迎消息到眼鏡
     */
    fun sendWelcomeMessage() {
        val welcomeText = """
            記賬助手已連接

             歡迎回來!

            今日消費記錄:${expenseManager.getTodayExpenseCount()}筆
            總金額:${expenseManager.getTodayTotalAmount()}元

             輕觸眼鏡觸控板開始記錄

            或對眼鏡説:"開始記賬"
        """.trimIndent()

        // 使用TTS播報歡迎信息
        sendTTSContent(welcomeText)
        notifyTtsAudioFinished()
    }

    /**
     * 處理從眼鏡端接收的ASR內容
     */
    fun handleGlassesAsrContent(asrContent: String): ValueUtil.CxrStatus? {
        return try {
            // 解析語音內容
            val expenseInfo = parseVoiceInput(asrContent)

            // 保存消費記錄
            expenseManager.addExpense(expenseInfo)

            // 發送成功反饋
            sendSuccessFeedback(expenseInfo)

            ValueUtil.CxrStatus.REQUEST_SUCCEED
        } catch (e: Exception) {
            Log.e(TAG, "處理ASR內容失敗", e)

            // 發送錯誤反饋
            sendErrorFeedback()

            ValueUtil.CxrStatus.REQUEST_FAILED
        }
    }

    /**
     * 解析語音輸入
     */
    private fun parseVoiceInput(input: String): ExpenseInfo {
        // 使用AI NLP解析消費信息
        val nlpResult = nlpProcessor.analyzeExpenseText(input)

        return ExpenseInfo(
            amount = nlpResult.amount,
            category = nlpResult.category,
            merchant = nlpResult.merchant,
            description = nlpResult.description,
            timestamp = System.currentTimeMillis(),
            source = "voice"
        )
    }
}

C、消費記錄管理器

class ExpenseManager(private val context: Context) {
    private val database = Room.databaseBuilder(
        context,
        ExpenseDatabase::class.java,
        "expense_database"
    ).build()

    private val expenseDao = database.expenseDao()

    /**
     * 添加消費記錄
     */
    suspend fun addExpense(expense: ExpenseInfo) {
        withContext(Dispatchers.IO) {
            expenseDao.insertExpense(expense)

            // 實時同步到雲端
            syncToCloud(expense)

            // 更新今日統計
            updateTodayStats()
        }
    }

    /**
     * 獲取今日消費統計
     */
    suspend fun getTodayStats(): TodayStats {
        return withContext(Dispatchers.IO) {
            val today = DateUtils.getTodayDate()
            val expenses = expenseDao.getExpensesByDate(today)

            TodayStats(
                totalAmount = expenses.sumOf { it.amount },
                expenseCount = expenses.size,
                categoryBreakdown = expenses.groupBy { it.category }
                    .mapValues { it.value.sumOf { expense -> expense.amount } },
                recentExpenses = expenses.takeLast(5)
            )
        }
    }

    /**
     * 獲取歷史記錄
     */
    suspend fun getExpenseHistory(startDate: Long, endDate: Long): List<ExpenseInfo> {
        return withContext(Dispatchers.IO) {
            expenseDao.getExpensesByDateRange(startDate, endDate)
        }
    }
}

D、晚間彙總管理器

class DailySummaryManager(private val context: Context) {
    private val TAG = "DailySummary"

    /**
     * 安排每日晚間彙總
     */
    fun scheduleDailySummary() {
        val workManager = WorkManager.getInstance(context)

        val summaryWork = PeriodicWorkRequestBuilder<DailySummaryWorker>(1, TimeUnit.DAYS)
            .setConstraints(
                Constraints.Builder()
                    .setRequiresBatteryNotLow(true)
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build()
            )
            .addTag("daily_summary")
            .build()

        workManager.enqueueUniquePeriodicWork(
            "daily_summary",
            ExistingPeriodicWorkPolicy.KEEP,
            summaryWork
        )
    }

    /**
     * 生成併發送晚間彙總
     */
    suspend fun generateAndSendDailySummary() {
        val todayStats = expenseManager.getTodayStats()

        // 生成彙總報告
        val summaryReport = generateSummaryReport(todayStats)

        // 發送到眼鏡端顯示
        sendSummaryToGlasses(summaryReport)

        // 發送推送通知
        sendSummaryNotification(summaryReport)

        Log.d(TAG, "晚間彙總完成:${todayStats.totalAmount}元")
    }

    /**
     * 生成彙總報告
     */
    private fun generateSummaryReport(stats: TodayStats): String {
        return buildString {
            appendLine("今日消費彙總")
            appendLine("=" * 20)
            appendLine(" 總金額:${stats.totalAmount}元")
            appendLine(" 筆數:${stats.expenseCount}筆")
            appendLine()
            appendLine("分類統計:")

            stats.categoryBreakdown.forEach { (category, amount) ->
                appendLine("• $category:${amount}元")
            }

            appendLine()
            appendLine("今日亮點:")
            appendLine(getDailyInsight(stats))

            appendLine()
            appendLine("明天見!")
        }
    }

    /**
     * 發送彙總到眼鏡端
     */
    private fun sendSummaryToGlasses(summaryReport: String) {
        // 使用TTS播報彙總
        sendTTSContent("今日消費彙總:總共消費${expenseManager.getTodayTotalAmount()}元")

        // 可以顯示詳細文本
        if (glassesConnectionManager.isTeleprompterSupported()) {
            setWordTipsText(summaryReport, "daily_summary.txt")
        }
    }

    /**
     * 獲取每日洞察
     */
    private fun getDailyInsight(stats: TodayStats): String {
        return when {
            stats.totalAmount > 500 -> "消費較多,注意理性消費哦"
            stats.expenseCount > 10 -> "消費頻次較高,可以考慮批量購買"
            stats.categoryBreakdown.containsKey("餐飲") && stats.categoryBreakdown["餐飲"]!! > 100 -> 
                "餐飲支出較多,可以嘗試自己做飯"
            else -> "消費合理,保持良好習慣"
        }
    }
}

E、消費記錄實體和DAO

@Entity(tableName = "expenses")
data class ExpenseInfo(
    @PrimaryKey val id: String = UUID.randomUUID().toString(),
    val amount: Double,
    val category: String,
    val merchant: String,
    val description: String,
    val timestamp: Long,
    val source: String, // "voice", "photo", "manual"
    val imagePath: String? = null,
    val location: String? = null
)

@Dao
interface ExpenseDao {
    @Query("SELECT * FROM expenses WHERE date(timestamp/1000, 'unixepoch') = date(:date/1000, 'unixepoch')")
    suspend fun getExpensesByDate(date: Long): List<ExpenseInfo>

    @Query("SELECT * FROM expenses WHERE timestamp BETWEEN :startDate AND :endDate")
    suspend fun getExpensesByDateRange(startDate: Long, endDate: Long): List<ExpenseInfo>

    @Insert
    suspend fun insertExpense(expense: ExpenseInfo)

    @Delete
    suspend fun deleteExpense(expense: ExpenseInfo)

    @Query("SELECT SUM(amount) FROM expenses WHERE date(timestamp/1000, 'unixepoch') = date(:date/1000, 'unixepoch')")
    suspend fun getTotalAmountByDate(date: Long): Double
}

data class TodayStats(
    val totalAmount: Double,
    val expenseCount: Int,
    val categoryBreakdown: Map<String, Double>,
    val recentExpenses: List<ExpenseInfo>
)

四、 核心技術實現要點

1. 語音識別優化

  • 使用離線路ASR引擎提高識別準確率
  • 針對財務術語進行訓練優化
  • 實現語音指令快捷操作

2. 圖像識別算法

  • 集成百度OCR/騰訊OCR API
  • 實現票據自動裁剪和增強
  • 建立商户名稱和類別的智能匹配

3. AI分類算法

class ExpenseClassifier {
    private val categories = listOf(
        "餐飲", "交通", "購物", "娛樂", "醫療", 
        "住房", "教育", "其他"
    )

    fun classifyExpense(merchant: String, description: String): String {
        val keywords = extractKeywords(merchant + " " + description)

        return when {
            keywords.any { it.contains("餐", "食", "廚", "味") } -> "餐飲"
            keywords.any { it.contains("車", "油", "路", "停") } -> "交通"
            keywords.any { it.contains("醫", "藥", "院") } -> "醫療"
            // 更多分類邏輯...
            else -> "其他"
        }
    }
}

4. 數據同步策略

  • 本地SQLite + 雲端MySQL雙存儲
  • 實現離線緩存和在線同步
  • 數據加密和隱私保護

五、 效果展示

用户體驗流程

  1. 早上出門:佩戴眼鏡,自動連接記賬助手
  2. 消費時
  • 語音方式:"記錄咖啡25元星巴克"
  • 或拍照小票自動識別
  1. 實時反饋:語音確認分類和金額
  2. 晚間8點:自動生成今日消費彙總報告

數據統計功能

  • 每日/每週/每月消費趨勢
  • 分類佔比餅圖
  • 商户消費排行
  • 異常消費提醒

技術亮點

  1. 免手操作:全程語音和眼部操作,真正的解放雙手
  2. AI智能識別:自動分類和金額識別,準確率>95%
  3. 實時反饋:即時語音確認,提升用户體驗
  4. 晚間彙總:自動化財務分析,培養良好記賬習慣
  5. 多端協同:眼鏡端快速操作,手機端數據管理

六、 商業價值

用户價值

  • 便捷性:解放雙手,隨時記錄
  • 準確性:AI智能識別,減少人工錯誤
  • 及時性:實時反饋和晚間彙總

商業價值

  • 數據價值:積累用户消費數據畫像
  • 生態價值:連接支付、電商、金融服務
  • 技術價值:AI+AR在垂直領域的創新應用

七、 未來展望

功能擴展

  1. 預算管理:設定月度預算,實時預警
  2. 投資建議:基於消費習慣提供理財建議
  3. 社交功能:與好友比較消費習慣
  4. 發票管理:自動歸類和管理髮票信息

技術升級

  1. 邊緣AI:眼鏡端本地AI推理
  2. 5G應用:實時雲端數據同步
  3. AR可視化:消費數據的AR展示
  4. 語音助手:更智能的AI對話體驗

總結:基於Rokid AI眼鏡的記賬本應用充分發揮了智能眼鏡的硬件優勢,通過語音識別、圖像識別和AI分析,打造了全新的免手操作記賬體驗。從日常消費的實時記錄到晚間的智能彙總,真正實現了"所見即所得,所説即所記"的智能財務管理理念。這個應用不僅提升了用户體驗,更為智能眼鏡在垂直領域的應用提供了有價值的探索。