1. 项目概述:当AI助手能听懂你的话

最近在折腾一个挺有意思的东西:一个能完全在本地运行、用语音控制的AI智能体。简单来说,就是想让电脑或树莓派这类设备,变成一个能听懂你说话、帮你处理事情的“贾维斯”。它不依赖任何云端API,所有对话、理解和任务执行都在你自己的设备上完成,核心诉求就两点: 隐私安全 离线可用

这个想法的源头,其实是对当前主流AI助手模式的一些“不满足”。很多智能助手确实方便,但你的每一条指令、每一次对话都可能经过云端,对于一些涉及个人隐私或敏感信息的场景,心里总有点不踏实。比如,你想让它帮你整理本地文档里的日程,或者处理一些包含个人信息的文件,交给云端总感觉像把日记本交给了陌生人。另一方面,网络不稳定或者干脆没网的时候,这些助手就立刻“罢工”了。所以,打造一个完全本地的、语音交互的AI代理,就成了一个很有吸引力的技术探索方向。

它适合谁呢?如果你是对隐私有较高要求的极客、喜欢折腾智能家居的开发者、或者单纯想深入理解现代AI技术栈(语音、语言模型、智能体)如何协同工作的学习者,那么这个项目会是一个绝佳的实践案例。整个过程会涉及到语音识别、大语言模型本地部署、智能体框架搭建以及软硬件集成等多个环节,堪称一次小型的技术全景之旅。

2. 核心架构设计与技术选型

2.1 整体工作流拆解

一个完整的语音控制本地AI智能体,其工作流是一个清晰的闭环。首先,你的声音通过麦克风被捕捉,转化为数字音频流。接着,本地运行的语音识别模型将这段音频转换成文本指令,比如“帮我查一下明天上午的日程”。然后,这段文本被送入同样运行在本地的 大语言模型 。LLM在这里扮演“大脑”的角色,它不仅要理解你的指令,还要根据预设的“技能”或工具调用能力,规划出执行步骤。例如,它可能会判断需要调用“读取日历文件”这个函数。智能体框架会执行这个函数调用,获取结果后,再交由LLM组织成自然语言回复。最后,这个文本回复通过本地运行的 文本转语音 模型,变成一段语音播放出来,完成一次交互。

这个流程的关键在于“完全本地化”。每一个环节——从声波到文字,从理解到执行,再从文字到声波——都发生在你的设备内部,数据不出本地,从而确保了隐私和离线能力。这要求我们对每一个组件的资源消耗和性能都有精细的考量。

2.2 关键技术组件选型与考量

技术选型是项目成败的基础,核心在于在性能、精度和资源消耗之间找到最佳平衡点。

1. 语音识别:轻量化与准确性的权衡 对于本地语音识别,我们不再能依赖像Whisper API那样强大但笨重的模型。Whisper的“large”版本虽然准确,但模型体积巨大,对硬件要求高。因此, 轻量化 是首要原则。一个非常好的选择是 OpenAI Whisper的“tiny”或“base”版本 ,或者专门为边缘设备优化的版本如 whisper.cpp 。这些版本在牺牲少量准确度(尤其是对于复杂专业词汇或带口音的语音)的情况下,大幅降低了模型大小和推理所需的内存与算力,使其能在树莓派4B甚至更低的硬件上实时运行。

注意 :选择语音识别模型时,务必测试其在你常用环境下的表现。背景噪音、麦克风质量、以及你的发音习惯,都会显著影响离线模型的识别率。通常需要准备一个小的测试集进行验证。

2. 大语言模型:本地部署的核心 这是整个系统的“大脑”。选型需要考虑三个核心维度: 模型大小、推理速度、对话能力 。像Llama 3、Qwen 2.5、Gemma等系列的 7B参数 版本,是当前本地部署的“甜点”选择。它们具备足够强的逻辑推理和指令跟随能力,同时经过量化(如GGUF格式的Q4_K_M量化)后,可以在16GB甚至8GB内存的消费级设备上流畅运行。

量化技术 是本地部署LLM的关键。它将模型参数的精度从FP32降低到INT4或INT5,从而大幅减少内存占用和提升推理速度,而性能损失在可控范围内。我们通常会选择 llama.cpp Ollama 作为推理引擎。llama.cpp兼容性极佳,效率突出;Ollama则提供了更便捷的模型管理和API调用方式,适合快速原型开发。

3. 智能体框架:连接大脑与手脚 LLM本身只是一个“思考者”,它需要框架来调用工具、执行动作。 LangChain LlamaIndex 是两大主流选择。LangChain功能全面,组件丰富,像一个“智能体工厂”,但学习曲线稍陡。LlamaIndex则更专注于数据连接和检索,对于需要让AI读取本地知识库的场景非常友好。对于这个项目,由于我们主要需要调用一些本地系统工具(如文件操作、执行命令),使用LangChain来定义工具、构建代理链是一个直观的方案。也可以考虑更轻量的方案,如直接利用LLM的 函数调用 能力,配合简单的Python脚本来实现。

4. 文本转语音:让AI“开口说话” TTS的选择相对直接。 Coqui TTS Piper 是优秀的开源选择,它们提供了多种语言的预训练模型,音质自然,且可以在CPU上高效运行。你需要根据偏好选择语音风格和语言。这一步的资源消耗通常远低于ASR和LLM。

3. 环境搭建与核心模块实现

3.1 基础开发环境配置

首先,我们需要一个清晰的Python环境。强烈建议使用 conda venv 创建独立的虚拟环境,避免包依赖冲突。

# 使用conda创建环境
conda create -n local_ai_agent python=3.10
conda activate local_ai_agent

# 或使用venv
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate  # Windows

接下来安装核心依赖。这里我们以LangChain和Whisper为例。

pip install openai-whisper  # 语音识别
pip install langchain langchain-community  # 智能体框架
pip install sounddevice pyaudio  # 音频采集
pip install TTS  # Coqui TTS,文本转语音
# 如果需要使用llama.cpp,则安装其Python绑定
pip install llama-cpp-python

实操心得 :安装 llama-cpp-python 时,如果遇到编译问题,可以尝试先安装CMake和C++编译器。在Mac上可能还需要 brew install cmake 。对于树莓派等ARM设备,编译过程可能较长,需要耐心。

3.2 语音识别模块实现

我们使用Whisper的 tiny 模型,它在速度和精度之间取得了很好的平衡。

import whisper
import numpy as np
import sounddevice as sd

class LocalSpeechRecognizer:
    def __init__(self, model_size="tiny"):
        # 加载模型,首次运行会自动下载
        self.model = whisper.load_model(model_size)
        print(f"Whisper模型 '{model_size}' 加载完成。")

    def record_audio(self, duration=5, samplerate=16000):
        """录制音频"""
        print(f"正在聆听...({duration}秒)")
        audio = sd.rec(int(duration * samplerate),
                       samplerate=samplerate,
                       channels=1,
                       dtype='float32')
        sd.wait()  # 等待录制结束
        return audio.flatten()

    def transcribe(self, audio_array, samplerate=16000):
        """将音频数组转录为文本"""
        # 确保音频为单声道,float32格式
        audio = audio_array.astype(np.float32)
        # 调用Whisper识别
        result = self.model.transcribe(audio, fp16=False) # 非GPU环境用fp16=False
        return result["text"].strip()

# 使用示例
if __name__ == "__main__":
    recognizer = LocalSpeechRecognizer("tiny")
    audio_data = recognizer.record_audio(duration=7)
    text = recognizer.transcribe(audio_data)
    print(f"识别结果:{text}")

这段代码创建了一个简单的语音识别类。 record_audio 函数使用 sounddevice 录制指定时长的音频, transcribe 函数则调用Whisper模型进行识别。 fp16=False 参数在纯CPU环境下是必须的。

3.3 本地大语言模型集成

这里我们展示如何使用 llama-cpp-python 加载一个量化后的GGUF模型文件。假设你已经下载了 llama-3-8b-instruct.Q4_K_M.gguf 模型文件。

from llama_cpp import Llama
from langchain.llms import LlamaCpp
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

class LocalLLM:
    def __init__(self, model_path):
        # 回调管理器,支持流式输出
        callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
        # 加载LlamaCpp模型,关键参数配置
        self.llm = LlamaCpp(
            model_path=model_path,
            temperature=0.7,        # 创造性,越高越随机
            max_tokens=512,         # 生成的最大token数
            top_p=0.95,             # 核采样参数,控制多样性
            callback_manager=callback_manager,
            verbose=False,          # 是否显示详细日志
            n_ctx=2048,             # 上下文窗口大小
            n_gpu_layers=0,         # CPU运行设为0,若有GPU可指定层数
        )
        print("本地LLM加载完成。")

    def generate(self, prompt):
        """生成回复"""
        response = self.llm.invoke(prompt)
        return response

# 使用示例
if __name__ == "__main__":
    llm = LocalLLM("./models/llama-3-8b-instruct.Q4_K_M.gguf")
    test_prompt = "用一句话解释什么是人工智能。"
    answer = llm.generate(test_prompt)
    print(f"\n模型回复:{answer}")

关键参数解析

  • n_ctx :决定了模型能“记住”多长的上下文对话。2048对于简单指令足够,若需长对话需增大,但内存消耗也会增加。
  • n_gpu_layers :如果系统有GPU,将此参数设置为一个大于0的数(如20),可以将模型的部分层卸载到GPU上,大幅提升推理速度。需要CUDA环境。
  • temperature :影响输出的随机性。0.1会让输出非常确定和重复,0.7-0.9适合创造性对话,1.0以上可能产生无意义内容。

3.4 智能体工具定义与链式构建

智能体的“能力”通过工具来定义。我们创建几个简单的本地工具示例。

from langchain.agents import Tool, AgentExecutor, create_react_agent
from langchain import hub
from datetime import datetime
import os

# 1. 定义工具函数
def get_current_time(input: str) -> str:
    """获取当前的日期和时间。输入参数忽略。"""
    now = datetime.now()
    return now.strftime("%Y年%m月%d日 %H:%M:%S")

def list_files_in_directory(input: str) -> str:
    """列出指定目录下的文件。输入应为目录路径。"""
    if not input or not os.path.isdir(input):
        return "错误:请输入一个有效的目录路径。"
    files = os.listdir(input)
    return f"目录 '{input}' 下的文件有:{', '.join(files[:10])}"  # 只显示前10个

def calculate_sum(input: str) -> str:
    """计算一组数字的和。输入应为用逗号分隔的数字字符串,如'1,2,3'。"""
    try:
        numbers = [float(x.strip()) for x in input.split(",")]
        total = sum(numbers)
        return f"这些数字的和是:{total}"
    except ValueError:
        return "错误:输入格式不正确,请使用逗号分隔的数字,例如 '1,2,3'。"

# 2. 将函数包装成LangChain工具
tools = [
    Tool(
        name="当前时间",
        func=get_current_time,
        description="当用户询问当前时间、日期或现在几点时使用此工具。输入参数忽略。"
    ),
    Tool(
        name="列出文件",
        func=list_files_in_directory,
        description="当用户要求列出某个文件夹中的文件时使用。输入应该是一个有效的目录路径字符串。"
    ),
    Tool(
        name="计算求和",
        func=calculate_sum,
        description="当用户要求计算一系列数字的总和时使用。输入应是用逗号分隔的数字字符串,例如'5,10,15'。"
    )
]

# 3. 创建智能体
def create_agent(llm):
    # 从LangChain Hub拉取一个ReAct提示词模板
    prompt = hub.pull("hwchase17/react")
    # 创建ReAct智能体
    agent = create_react_agent(llm, tools, prompt)
    # 创建执行器
    agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
    return agent_executor

# 使用示例
if __name__ == "__main__":
    # 假设llm是已初始化的LocalLLM实例
    from local_llm import LocalLLM
    llm_instance = LocalLLM("./models/llama-3-8b-instruct.Q4_K_M.gguf").llm
    agent = create_agent(llm_instance)

    query = "请告诉我现在的时间,然后计算1.5, 2.5和3的和。"
    result = agent.invoke({"input": query})
    print(f"\n最终结果:{result['output']}")

这个智能体使用了 ReAct 框架,它会让LLM以“思考 -> 行动 -> 观察”的循环来解决问题。 verbose=True 会让执行过程打印出来,方便调试。当LLM决定使用工具时,它会生成一个类似 Action: 当前时间 的指令,执行器便会调用对应的工具函数。

3.5 文本转语音模块集成

最后,让AI的回复“说”出来。我们使用Coqui TTS。

from TTS.api import TTS
import numpy as np
import sounddevice as sd

class LocalTTS:
    def __init__(self, model_name="tts_models/en/ljspeech/tacotron2-DDC"):
        # 初始化TTS,指定模型
        self.tts = TTS(model_name=model_name, progress_bar=False, gpu=False)
        print("TTS模型加载完成。")

    def speak(self, text, output_wav_path=None):
        """将文本转换为语音并播放,可选保存为文件"""
        if output_wav_path:
            # 保存为wav文件
            self.tts.tts_to_file(text=text, file_path=output_wav_path)
            print(f"语音已保存至:{output_wav_path}")
        # 在内存中生成音频数据并播放
        wav = self.tts.tts(text=text)
        wav_np = np.array(wav)
        sd.play(wav_np, samplerate=22050)  # 注意采样率需与模型匹配
        sd.wait()
        print("播放完毕。")

# 使用示例
if __name__ == "__main__":
    tts = LocalTTS()
    tts.speak("Hello, I am your local AI assistant. How can I help you today?")
    # tts.speak("你好,我是你的本地AI助手。", output_wav_path="greeting.wav")

注意 :TTS模型的选择会影响音质和语言。 en/ljspeech/tacotron2-DDC 是英文模型。如果需要中文语音,可以寻找并指定中文TTS模型,例如 zh-CN/baker/tacotron2-DDC-GST (如果可用)。首次运行会下载模型,请确保网络通畅。

4. 系统集成与主循环逻辑

将以上所有模块串联起来,形成完整的交互闭环。

import time
from speech_recognizer import LocalSpeechRecognizer
from local_llm import LocalLLM
from agent_manager import create_agent
from local_tts import LocalTTS

class VoiceControlledAIAgent:
    def __init__(self, llm_model_path, tts_model_name="tts_models/en/ljspeech/tacotron2-DDC"):
        print("初始化语音控制AI智能体...")
        self.asr = LocalSpeechRecognizer("base")  # 使用base模型,精度更高一些
        self.llm_wrapper = LocalLLM(llm_model_path)
        self.agent = create_agent(self.llm_wrapper.llm)
        self.tts = LocalTTS(tts_model_name)
        print("所有模块初始化完成!")

    def process_command(self, audio_duration=7):
        """处理单次语音命令的完整流程"""
        # 1. 录音
        print("\n" + "="*50)
        print("请说话...")
        audio = self.asr.record_audio(duration=audio_duration)

        # 2. 语音识别
        print("正在识别语音...")
        user_text = self.asr.transcribe(audio)
        if not user_text or len(user_text.strip()) < 2:
            print("未识别到有效指令。")
            return
        print(f"您说:{user_text}")

        # 3. 智能体处理
        print("AI正在思考...")
        try:
            agent_response = self.agent.invoke({"input": user_text})
            ai_text = agent_response['output']
        except Exception as e:
            ai_text = f"处理指令时出现错误:{e}"
        print(f"AI回复:{ai_text}")

        # 4. 语音合成与播放
        print("AI正在说话...")
        self.tts.speak(ai_text)

    def run_interactive_loop(self):
        """运行交互循环"""
        print("\n语音控制AI智能体已启动!")
        print("说出你的指令(例如:'现在几点?' 或 '列出/home/pi/documents目录下的文件')")
        print("说'退出'或'停止'来结束程序。")
        while True:
            self.process_command()
            # 简单检查是否要退出(基于识别文本)
            # 注意:由于识别可能不准,退出指令可能需要更鲁棒的检查
            time.sleep(1)  # 每次循环间隔,避免过热

if __name__ == "__main__":
    # 请根据你的实际路径修改
    MODEL_PATH = "./models/llama-3-8b-instruct.Q4_K_M.gguf"
    agent = VoiceControlledAIAgent(MODEL_PATH)
    agent.run_interactive_loop()

这个主类 VoiceControlledAIAgent 将四个核心模块整合在一起。 run_interactive_loop 方法启动了一个持续监听-处理-回复的循环。每次循环中,它录制一段音频,识别成文本,交给智能体处理,最后将智能体的文本回复用语音播放出来。

5. 性能优化与部署实践

5.1 硬件要求与资源管理

本地AI智能体对硬件有一定要求,主要瓶颈在 内存 CPU/GPU

  • 树莓派4B (4GB/8GB RAM) :这是挑战的极限。可以运行Whisper tiny和量化到Q4的2B-3B参数模型(如Phi-2, Qwen1.5-1.8B)。运行7B模型会非常吃力,甚至因内存不足而失败。务必使用交换空间,并关闭所有不必要的后台服务。
  • x86旧笔记本/迷你主机 (8GB RAM) :这是入门级门槛。可以较为流畅地运行Whisper base和7B模型的Q4量化版。推理速度可能在每秒2-5个token,响应会有明显延迟,但可交互。
  • 配备GPU的台式机/服务器 (16GB+ RAM, NVIDIA GPU) :这是理想环境。利用 n_gpu_layers 将模型大部分层加载到GPU显存中,推理速度可提升10倍以上,达到实时对话体验。显存大小决定了能加载的模型尺寸(例如,RTX 4060 8G可流畅运行7B Q4模型)。

资源监控命令 : 在Linux/macOS下,运行程序时,另开一个终端使用 htop top 命令观察CPU和内存占用。对于树莓派, vcgencmd measure_temp 可以查看核心温度,防止过热降频。

5.2 延迟优化技巧

延迟是影响体验的关键。可以从以下几个层面优化:

  1. 语音识别优化

    • 使用VAD :集成语音活动检测,只在检测到人声时才录制和识别,避免处理静音片段,减少无效计算和等待时间。 webrtcvad 库是一个不错的选择。
    • 流式识别 :如果使用支持流式处理的ASR引擎(如faster-whisper),可以在说话的同时就开始识别,实现“边说边转”。
  2. LLM推理优化

    • 调整 max_tokens :限制每次生成的最大长度,避免AI“长篇大论”拖慢响应。
    • 使用更高效的推理后端 :除了llama.cpp,可以尝试 vLLM (如果支持你的模型和硬件),它专门为高吞吐量、低延迟的LLM服务设计。
    • 缓存 :对于常见、固定的问题(如“你是谁?”),可以设置一个简单的内存缓存,直接返回预置答案,绕过LLM推理。
  3. 流水线并行

    • 当前流程是串行的:录音 -> ASR -> LLM -> TTS。一个高级优化思路是 部分并行 。例如,在LLM生成文本的前几个token后,就可以开始启动TTS的预处理,而不是等全部文本生成完毕。

5.3 部署为常驻服务

要让这个智能体像“管家”一样随时待命,需要将其部署为系统服务。

在Linux系统上使用systemd : 创建一个服务文件,例如 /etc/systemd/system/local-ai-agent.service

[Unit]
Description=Local Voice-Controlled AI Agent
After=network.target sound.target
Wants=network.target

[Service]
Type=simple
User=pi  # 替换为你的用户名
WorkingDirectory=/home/pi/voice_ai_agent  # 替换为你的项目路径
Environment="PATH=/home/pi/venv/bin"  # 虚拟环境路径
ExecStart=/home/pi/venv/bin/python /home/pi/voice_ai_agent/main.py
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

然后启用并启动服务:

sudo systemctl daemon-reload
sudo systemctl enable local-ai-agent.service
sudo systemctl start local-ai-agent.service
# 查看状态
sudo systemctl status local-ai-agent.service
# 查看日志
sudo journalctl -u local-ai-agent.service -f

这样,设备开机后服务会自动启动,并在崩溃后尝试重启。你可以通过查看日志来监控运行状态。

6. 常见问题排查与调试心得

6.1 语音识别准确率低

这是最常见的问题,尤其是在有环境噪音或使用廉价麦克风时。

  • 症状 :识别出的文本与所说内容完全不符或支离破碎。
  • 排查步骤
    1. 检查音频输入 :首先确认麦克风是否被正确识别和选中。可以使用 arecord -l (Linux)或系统录音工具测试麦克风是否能正常录音。
    2. 优化录音参数 :尝试调整 sounddevice 的采样率( samplerate )和设备ID( device )。采样率通常为16000Hz或22050Hz,需与模型训练时匹配。Whisper期望16kHz。
    3. 预处理音频 :在将音频送入模型前,可以进行简单的预处理,如归一化( audio = audio / np.max(np.abs(audio)) )和降噪(使用 noisereduce 库)。这对于提升低质量麦克风的识别率有奇效。
    4. 更换模型 :如果使用 tiny 版不准,可以尝试 base 甚至 small 版,但要注意性能下降。也可以尝试其他轻量级ASR模型,如 Vosk ,它对特定场景可能有更好表现。
    5. 环境降噪 :物理上改善录音环境是最根本的方法。

6.2 大语言模型加载失败或推理极慢

  • 症状 :程序在加载模型时崩溃,或加载后生成每个词都需要数秒。
  • 排查与解决
    1. 内存不足 :这是崩溃的主因。使用 free -h 或任务管理器检查可用内存。确保模型文件大小(GGUF文件大小)远小于你的可用内存。例如,一个7B Q4模型约4-5GB,系统至少需要8GB内存才比较安全。
    2. 量化等级过高 :如果你使用了Q2或Q3等更激进的量化,虽然模型更小,但精度损失可能导致输出乱码或逻辑错误。建议从Q4_K_M或Q5_K_M开始尝试。
    3. 未使用GPU加速 :在支持CUDA的机器上,务必设置 n_gpu_layers 。你可以尝试将其设置为一个很大的数(如999),让库自动决定卸载所有可能层到GPU。使用 nvidia-smi 命令确认GPU是否被使用。
    4. 线程数设置 :对于纯CPU推理, llama-cpp-python 可以通过 n_threads 参数指定使用的CPU线程数。通常设置为物理核心数能获得较好性能。在初始化时传入: LlamaCpp(..., n_threads=4)

6.3 智能体不调用工具或调用错误

  • 症状 :LLM直接回答了关于时间或计算的问题,而没有调用我们定义的 当前时间 计算求和 工具。
  • 排查与解决
    1. 工具描述不清 :检查Tool的 description 字段。这个描述是LLM决定是否调用工具的唯一依据。描述必须清晰、准确,并包含触发条件。例如,“当用户询问当前时间、日期或现在几点时使用此工具”就比“获取时间”要好得多。
    2. 提示词模板问题 :ReAct代理的提示词模板引导LLM按照“Thought/Action/Action Input/Observation”的格式思考。如果LLM不按这个格式输出,执行器就无法解析。确保你使用的 prompt 模板是适合工具调用场景的。 hwchase17/react 是LangChain官方维护的一个可靠选择。
    3. LLM能力不足 :较小的或指令跟随能力较弱的模型可能无法可靠地理解并使用工具。尝试换一个更强大的模型(如从7B换到8B或更大,或换用指令微调更充分的模型系列)。
    4. 开启详细日志 :设置 AgentExecutor(..., verbose=True) ,观察LLM的完整思考链。这能帮你看到它是如何思考、为什么决定不调用工具的,是调试的最重要手段。

6.4 音频播放异常或没有声音

  • 症状 :程序运行无报错,但听不到TTS播放的声音。
  • 排查步骤
    1. 检查输出设备 sounddevice 默认使用系统默认播放设备。可以通过 sd.query_devices() 列出所有设备,并在 sd.play() 中指定正确的 device 参数。
    2. 采样率匹配 :TTS模型生成的音频有一个固定的采样率(如22050Hz)。在 sd.play() 时, samplerate 参数必须与之匹配,否则播放速度会不对。查看TTS模型文档或打印生成音频的采样率。
    3. 保存文件测试 :先将TTS输出保存为WAV文件(使用 tts.tts_to_file ),然后用系统播放器打开。如果能正常播放,说明问题出在 sounddevice 播放环节;如果不能,说明TTS生成环节有问题。
    4. 权限问题 (Linux):在某些系统上,用户可能没有直接播放音频的权限。可以尝试将用户加入 audio 组: sudo usermod -a -G audio $USER ,然后注销重新登录。

这个项目从构思到实现,是一段充满挑战和成就感的旅程。最大的体会是, 平衡的艺术贯穿始终 :在模型精度与推理速度之间,在功能丰富性与系统资源之间,在开发复杂度与用户体验之间。每一次优化和调试,都让你对底层技术栈的理解更深一层。它不仅仅是一个可用的工具,更是一个绝佳的、全景式的AI应用开发学习案例。当你第一次听到它用你自己的声音(如果你训练了自定义TTS)流畅地回答出本地文件列表时,那种一切尽在掌控的感觉,是使用任何云端API都无法替代的。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐