site logo

Marico's space

在 WhatsApp 上构建 AI 语言导师:技术现实

AI技术与应用 2026-04-28 11:56:14 5

原文:Building AI Language Tutors on WhatsApp: The Technical Reality|译者前言:本文来自 dev.to,观点有价值,转写发布供读者参考。

原文发布于 AIdeazz — 交叉发布于此,保留规范链接。

当我推出 EspaLuz(我们的西班牙语导师 agent)时,我刻意选择了 WhatsApp 而不是构建另一个 Web 应用。这不是因为它很流行,而是因为消息平台解决了大多数 AI 构建者忽略的实际问题:身份验证、支付、语音消息和用户习惯。在处理了数千个导师课程后,以下是在 WhatsApp 上构建 AI 语言导师时真正重要的事情。

为什么 WhatsApp 优于你的自定义聊天 UI

大多数开发者默认构建 Web 界面。我理解——你可以控制一切。但你实际在构建的是:身份验证流程、支付处理、语音录制权限、移动端适配、离线处理和通知系统。与此同时,WhatsApp 给了你 27 亿已经知道如何发送语音消息的用户。

真正的优势不是用户数量。而是既定的行为模式。用户已经会向朋友发送语音笔记,在许多国家已经通过 WhatsApp 支付,已经习惯异步对话。你不需要教授新的 UI 模式——你是在利用现有习惯。

从我们的 Oracle Cloud 基础设施来看,技术集成很简单。WhatsApp Business API webhooks 命中我们的端点,我们通过 agent 管道处理,然后响应。无需前端部署、无需 CDN 配置、无需应用商店审核。只有 API 调用。

让开发者惊讶的约束:24 小时消息窗口。如果用户不先给你发消息,你不能在模板消息之外发起联系。这强制做出好的架构决策——你构建的是用户主动学习而不是垃圾通知。

对话学习的记忆架构

语言学习需要与客户支持不同的记忆。一个学生在第 3 课说"我搞不清 ser 和 estar 的区别",这需要影响第 30 课。但将每条消息存储在向量数据库中既昂贵又缓慢。

我们的方法:双层记忆,Redis 用于热状态,PostgreSQL 用于学习历史。每个对话维护:

{
  "user_id": "whatsapp:+50712345678",
  "current_level": "A2",
  "active_errors": ["ser/estar", "preterite_irregular"],
  "conversation_context": [...last_5_exchanges],
  "voice_preference": true,
  "payment_status": "active_until_2024_12_31"
}

关键洞察:我们不嵌入所有内容。西班牙语动词变位不需要语义搜索——它们需要结构化跟踪。我们维护错误模式表:

CREATE TABLE error_patterns (
  user_id VARCHAR(255),
  error_type VARCHAR(100),
  frequency INTEGER,
  last_seen TIMESTAMP,
  corrected_successfully BOOLEAN
);

生成响应时,我们会查询最近的错误并将它们注入提示中。上周混淆了"por"和"para"的用户会在新语境中巧妙地接触到这些介词。无需 RAG——只需 SQL 连接。

对于对话上下文,我们在 Redis 中保留一个滑动窗口,TTL 为 1 小时。这处理了"我刚才问了什么?"的查询,而无需维护无限历史。较旧的对话会被总结并存储为学习检查点。

真正有效的语音消息处理

纯文本辅导错过了语言学习的要点。发音很重要。WhatsApp 语音消息解决了硬件复杂性——用户已经知道如何录制和发送。

技术栈:WhatsApp 发送 .opus 文件 → 转换为 .wav → 发送到 Groq 的 Whisper API → 获取转录和置信度分数。关键部分(大多数人会忽略的):处理口音和学习者错误。

默认 Whisper 会将学习者的西班牙语转录成乱码。我们通过提示工程和后处理解决了这个问题:

def process_learner_audio(audio_file, expected_level="A2"):
    # 带语言提示的 Whisper
    transcription = groq_whisper(
        audio_file,
        language="es",
        prompt="Spanish learner, may have accent errors"
    )

# 基于置信度的纠正 if transcription.confidence < 0.7: # 运行音素匹配 corrected = match_common_errors(transcription.text) return { "heard": transcription.text, "likely_intended": corrected, "confidence": transcription.confidence }

return {"heard": transcription.text, "confidence": transcription.confidence}

用户体验:他们发送语音,收到文本纠正和音频回复。当发音纠正重要时,我们使用 ElevenLabs 生成音频回复,语法解释则仅用文本。这种混合方法降低成本同时保持教学质量。

无需支付麻烦的支付集成

传统 SaaS 计费不适合对话界面。用户不想离开 WhatsApp 来管理订阅。我们集成了两种真正被使用的方法:

  1. WhatsApp Pay(在可用地区):直接应用内支付。用户输入"升级",收到支付请求,在不离开聊天的情况下完成。API 发送支付确认 webhooks——我们立即更新他们的状态。
  2. 带上下文的支付链接:对于没有 WhatsApp Pay 的地区,我们生成保持对话状态的个性化支付链接。用户点击、支付、返回聊天时已启用访问。无需创建账户、无需密码重置。

架构秘密:将支付状态视为对话状态,而非用户账户数据。每条消息都会检查支付有效性:

async def check_access(user_id):
    # 先检查 Redis(缓存 5 分钟)
    status = await redis.get(f"payment:{user_id}")
    if status:
        return json.loads(status)

# 数据库回退 payment = await db.fetch_one( "SELECT expires_at FROM payments WHERE user_id = ?", user_id )

if payment and payment.expires_at > datetime.now(): # 缓存正向结果 await redis.setex( f"payment:{user_id}", 300, json.dumps({"valid": True}) ) return {"valid": True}

return {"valid": False}

这种模式处理了消息的现实:用户会休眠数周,然后回来期望连续性。他们的支付状态随对话流动,而不是某个单独的账户系统。

语言教学的多 Agent 架构

单次 LLM 调用无法创建好的辅导。我们运行三个专业 agent:

  1. 错误检测 Agent(Claude 3.5 Sonnet):分析用户输入的语法/词汇错误。返回结构化错误数据,而非纠正。
  2. 课程 Agent(Groq Llama 3):根据错误模式和学习进度决定下一步教什么。快速推理在这里很重要——用户能感受到延迟。
  3. 响应生成 Agent(Claude 3.5 Sonnet):使用错误分析和课程决策创建实际的教学响应。

这种分离看起来像过度工程,直到你遇到边缘情况。一个用户说"Yo soy fue al tienda"需要与发音错误的"Fui a la tienda ayer"不同的处理方式。错误 agent 进行分类(动词变位错误 + 冠词性错误),课程 agent 决定优先级(先修复动词),响应 agent 制定纠正方案。

管道:

async def process_learning_message(user_input, user_state):
    # 并行分析
    error_task = analyze_errors(user_input, user_state.level)
    context_task = get_user_context(user_state.user_id)

errors, context = await asyncio.gather(error_task, context_task)

# 课程决策(快速 Groq 调用) teaching_focus = await decide_curriculum( errors, context.recent_errors, context.current_topic )

# 生成响应(质量优先的 Claude 调用) response = await generate_teaching_response( user_input, errors, teaching_focus, context )

# 更新用户学习状态 await update_learning_state( user_state.user_id, errors, teaching_focus )

return response

关键是:agent 共享记忆但有不同的提示和模型。错误检测在每条消息上运行,课程决策缓存 5 条消息(减少 Groq 调用),响应生成获得完整上下文。

没人提的生产环境约束

在规模上运行 AI 语言导师 WhatsApp 机器人揭示了痛苦的真相:

速率限制:WhatsApp Business API 有复杂的速率限制——不仅仅是每秒消息数,还有每个电话号码、每个对话状态的限制。我们实现带抖动的指数退避:

async def send_with_backoff(phone_number, message):
    for attempt in range(5):
        try:
            return await whatsapp_api.send(phone_number, message)
        except RateLimitError:
            wait_time = (2 ** attempt) + random.uniform(0, 1)
            await asyncio.sleep(wait_time)

# 最终尝试失败 - 排队稍后发送 await queue_for_batch_send(phone_number, message)

消息长度:WhatsApp 在 4096 字符处截断。语法解释经常达到这个限制。我们智能分块——完整的思想,而非字符计数。

时区混乱:用户在不同时区的随机时间学习。预定课程不起作用。相反,我们跟踪活动模式,在他们的活跃时段发送温和的提醒模板。

成本管理:每个用户大约产生:

  • 每节课 15 条消息
  • 3 次 Whisper API 调用(语音消息)
  • 2 次 Claude 调用(分析 + 响应)
  • 5 次 Groq 调用(快速决策)

规模化后,这些成本累积。我们激进地缓存——常见错误解释、发音乐谱、语法规则。并非每个响应都需要新鲜生成。

真正推动留存的因素

如果用户不回来,技术架构毫无意义。从我们的数据:

  • 语音消息将留存率提高 3 倍(相比纯文本)
  • 即时错误纠正优于延迟的"课程总结"
  • 支付摩擦比定价杀死更多用户
  • 异步对话比预定课程更适合学习

令人惊讶的洞察:用户不想要游戏化。他们想发送一条带有他们蹩脚西班牙语的语音消息,然后得到耐心、具体的反馈。没有积分、没有排行榜、没有每日连续记录。只有在他们的实际生活活动之间进行的对话练习。

在消息平台上构建强制这种简单性。你无法添加复杂的 UI。你只剩下核心学习循环:尝试 → 反馈 → 改进。

对于考虑这条路的开发者:从约束开始。WhatsApp 的限制会强制比任何系统设计文档更好的架构。为间歇性注意力构建,为语音优先交互设计,优化响应质量而非响应速度。

未来不是取代人类导师——而是在真实课程之间使练习变得可及。在 WhatsApp 上的 AI 语言导师填补了你通勤、排队或睡前有五分钟时的空白。这才是语言学习真正发生的时候。

— Elena Revicheva · AIdeazz · Portfolio