很多开发者都曾想过提升自己的英语口语能力,但苦于没有真实的对话环境和及时的反馈。传统的学习软件要么是单向的输入,要么是与预设脚本的僵硬对话,缺乏真实感和互动性。随着大语言模型(LLM)能力的爆发,我们终于可以亲手打造一个专属的、智能的、24小时在线的AI口语陪练伙伴。本文将带你从零开始,基于开源大模型和语音技术,构建一个完整的“AI英语口语陪练”应用。无论你是想学习技术实现,还是想为自己创造一个实用的学习工具,这篇文章都将提供从环境搭建、核心原理到代码实现的完整闭环方案。
1. 项目概述与核心价值
1.1 什么是AI口语陪练?
AI口语陪练是一个结合了自动语音识别(ASR)、大语言模型(LLM)和文本转语音(TTS)技术的智能应用。它的工作流程模拟了真实的人类对话:
用户说话 :应用通过麦克风采集你的英语语音。
语音转文字 :ASR模型将你的语音实时转换为文本。
生成对话回复 :LLM(如ChatGLM、Qwen、Llama等)扮演对话伙伴的角色,根据你的文本内容,生成符合语境、自然流畅的英文回复文本。
文字转语音 :TTS模型将LLM生成的回复文本转换为逼真的英语语音,播放出来。
这样,你就完成了一次与AI的完整口语对话循环。其核心价值在于提供了一个安全、可定制、无限耐心的练习环境 ,你可以随时就任何话题进行练习,并获得语法正确、表达地道的反馈。
1.2 技术栈选型
为了实现一个功能完整且可本地部署(保护隐私)的应用,我们将采用以下技术栈:
后端框架 :FastAPI 。轻量级、异步支持好,非常适合构建实时性要求较高的API服务。
大语言模型 :Ollama 。一个强大的本地大模型运行和管理的工具,可以轻松在本地运行多种开源LLM,如 llama3.2、qwen2.5 等,无需GPU也能运行较小参数模型。
语音识别 :OpenAI Whisper (离线版)。开源、精准的语音识别模型,支持多种语言,我们可以将其集成到本地。
文本转语音 :Edge-TTS 或 VITS 。Edge-TTS 利用微软Edge浏览器的在线语音合成接口,免费且音质不错;若需完全离线,可考虑 VITS 等本地TTS模型。
前端 :简单的HTML/JavaScript网页。用于提供录音按钮、显示对话记录和播放音频。
音频处理 :PyAudio / SoundDevice 用于录音,ffmpeg 用于音频格式处理。
2. 环境准备与项目初始化
2.1 系统与Python环境
操作系统 :Windows 10/11, macOS, 或 Linux (Ubuntu 22.04+)。本文以Windows为例,其他系统命令略有不同。
Python版本 :>= 3.9。推荐使用 3.10 或 3.11,以获得更好的兼容性。
包管理工具 :使用 pip 和 venv 创建虚拟环境。
首先,创建项目目录并初始化虚拟环境。
2.2 安装核心依赖
创建 requirements.txt 文件,并安装依赖。
TXT
复制
3
uvicorn[standard]==0.24.0
4
openai-whisper==20231117
11
python-multipart==0.0.6
使用pip安装:
BASH
复制
1
pip install -r requirements.txt
注意 :Whisper 依赖 PyTorch。上述命令会安装CPU版本的PyTorch。如果你有NVIDIA GPU并希望加速,请先根据 PyTorch官网 的指引安装对应CUDA版本的PyTorch,再安装其他依赖。
2.3 安装并配置Ollama
Ollama是我们运行本地大模型的核心。前往 Ollama官网 下载并安装对应操作系统的客户端。
安装完成后,打开终端(或命令提示符/PowerShell),拉取一个适合对话的模型。对于英语口语陪练,一个7B参数左右的模型在性能和资源消耗上比较平衡。
运行模型以测试是否成功:
在出现的提示符后输入 Hello,看到模型回复即表示成功。按 Ctrl+D 退出。
3. 核心模块设计与实现
我们的应用主要分为三个后端服务模块和一个前端界面。
3.1 项目结构
创建如下项目结构:
TEXT
复制
4
│ ├── main.py # FastAPI 主应用
5
│ ├── llm_client.py # Ollama 客户端
6
│ ├── stt_engine.py # 语音识别引擎 (Whisper)
7
│ └── tts_engine.py # 文本转语音引擎 (Edge-TTS)
11
├── temp_audio/ # 临时存放音频文件
3.2 大语言模型客户端 (llm_client.py)
这个模块负责与本地运行的Ollama服务交互,发送用户文本并获取AI回复。
PYTHON
复制
6
def __init__ (self, base_url="http://localhost:11434" , model="llama3.2" ):
9
:param base_url: Ollama服务地址,默认本地11434端口。
10
:param model: 要使用的模型名称。
12
self.base_url = base_url
14
self.api_url = f"{base_url} /api/generate"
16
self.system_prompt = """You are a friendly and patient English tutor. Your task is to have a natural conversation with the user to help them practice spoken English.
18
1. Respond in English only.
19
2. Keep your responses concise and conversational (1-2 sentences usually).
20
3. If the user makes a grammatical error, gently correct them in a supportive way within your response.
21
4. Ask follow-up questions to keep the conversation flowing.
22
5. Adapt to the user's apparent proficiency level.
25
def generate_response (self, user_message: str , conversation_history: list = None ) -> str :
28
:param user_message: 用户输入的文本。
29
:param conversation_history: 可选的对话历史,格式为 [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]
34
if self.system_prompt:
35
messages.append({"role" : "system" , "content" : self.system_prompt})
37
if conversation_history:
38
messages.extend(conversation_history[-6 :])
40
messages.append({"role" : "user" , "content" : user_message})
45
"prompt" : user_message,
57
response = requests.post(self.api_url, json=data, timeout=60 )
58
response.raise_for_status()
59
result = response.json()
60
return result.get("response" , "Sorry, I didn't get that." ).strip()
61
except requests.exceptions.RequestException as e:
62
print (f"Error calling Ollama API: {e} " )
63
return "I'm having trouble connecting to my brain. Please try again."
3.3 语音识别引擎 (stt_engine.py)
使用Whisper将用户上传的音频文件转换为文本。
PYTHON
复制
7
def __init__ (self, model_size="base" ):
10
:param model_size: Whisper模型大小,可选 tiny, base, small, medium, large。越大越准,越慢。
13
print (f"Loading Whisper {model_size} model..." )
14
self.model = whisper.load_model(model_size)
15
print ("Model loaded." )
17
def transcribe_audio (self, audio_file_path: str ) -> str :
20
:param audio_file_path: 音频文件路径(支持wav, mp3, m4a等)。
23
if not os.path.exists(audio_file_path):
24
return "Error: Audio file not found."
28
result = self.model.transcribe(audio_file_path, fp16=False )
29
text = result["text" ].strip()
30
return text if text else "I didn't catch that. Could you please repeat?"
31
except Exception as e:
32
print (f"Transcription error: {e} " )
33
return "Sorry, there was an error processing your speech."
3.4 文本转语音引擎 (tts_engine.py)
使用Edge-TTS将AI回复的文本转换为语音,并保存为MP3文件。
PYTHON
复制
7
def __init__ (self, voice="en-US-AriaNeural" ):
10
:param voice: 语音名称。推荐英语语音:en-US-AriaNeural, en-US-GuyNeural, en-GB-SoniaNeural
14
async def text_to_speech_async (self, text: str , output_path: str ) -> bool :
18
:param output_path: 输出MP3文件路径。
19
:return: 成功返回True,失败返回False。
22
communicate = edge_tts.Communicate(text, self.voice)
23
await communicate.save(output_path)
25
except Exception as e:
26
print (f"TTS error: {e} " )
29
def text_to_speech (self, text: str , output_path: str ) -> bool :
33
return asyncio.run(self.text_to_speech_async(text, output_path))
4. 构建FastAPI后端服务 (main.py)
现在我们将所有模块整合到一个FastAPI应用中,提供WebSocket和HTTP接口。