我的AI女友
看着痞老板对着机器人老婆凯伦敲敲打打,为什么不能整一个AI女友呢?
我的AI女友
起因:
这事得从我那倒霉兄弟说起,上个月他谈了多年的女朋友,因为各种理由闹掰了。那几天我天天陪他吃烧烤,听到的苦水比啤酒泡沫还多,其实我当时心里也比较害怕的,毕竟咱也算是一表人才,万一他整多把兄弟我看成了他可爱的女盆友给咱来一手“男上加男”我这辈子幸福就毁掉,没办法我只能发挥一下我聪明的小脑瓜子得给他好好想想办法,在我一筹莫展刷着安慰失恋人士的某音的时候,某音播放的《海绵宝宝》救了我。看着痞老板对着机器人老婆凯伦敲敲打打,我大腿都快拍肿了——为什么不能给他整一个AI女友呢?
实现原理
开局一张图,知识全靠学
什么是LLM?
LLM(Large Language Model,大语言模型),相信大家都用过deepseek,千问等等之类的吧,这种都为大语言模型。这是一种基于深度学习的人工智能技术,通过学习海量的文本数据来理解和生成自然语言文本。这些模型通常包含数百亿(或更多)参数,能够捕捉语言的复杂结构、语义和上下文关系,从而在各种自然语言处理任务中展现出惊人的能力。大型语言模型在文本生成、文本分类、机器翻译、情感分析等领域有广泛的应用。
什么是TTS?
TTS(Text-to-Speech,文语转换)是一种用于将文本信息转换成自然语音的技术,应该大家都用过小说软件看小说吧,小说软件中的自动读书的软件就可以理解为我们的TTS。TTS其目标是让计算机能够以清晰自然的声音,使用各种语言和情绪来朗读文本,实现类似于人类甚至更强的说话能力
什么是ASR ?
ASR(Automatic Speech Recognition,自动语音识别)是一种将人类语音转换为文本的技术。简单来说这个就像看视频的实时字幕,它可以让计算机“听懂”人类的语言,并将其转化为可编辑或可处理的文本信息。ASR技术是语音交互领域的核心技术之一,广泛应用于各种场景中。
总结:
了解完这些我们再仔细看那个这个图,这个图说明了LLM(大语言模型)、TTS(文语转换)和ASR(自动语音识别)之间的关系以及它们在语音交互中的应用。
ASR(自动语音识别)功能:将人类的语音转换为文本->LLM(大语言模型)功能:理解和生成自然语言文本->TTS(文语转换)功能:将文本信息转换为自然语音,ASR、LLM和TTS三者协同工作,构成了完整的语音交互系统,通过这三项技术的结合,计算机能够实现与人类的自然语音交互,广泛应用于语音助手、智能客服、实时字幕等场景中。
如何实现?
说到这里,相信大家应该心里明白了相关技术的实现原理了。后面我们会带大家根据这些原理去实现我们的AI女友。
在开始之前,先给家人们安利一波阿里的魔搭社区!
什么是魔搭社区?
魔搭社区(ModelScope)是由阿里巴巴推出的一个开放的AI模型平台,旨在为开发者、研究者和企业提供丰富的AI模型资源和工具,帮助大家快速构建和部署AI应用,魔搭社区提供了海量的预训练模型,涵盖自然语言处理(NLP)、计算机视觉(CV)、语音处理等多个领域,满足不同场景的需求,社区中的模型大多经过优化和封装,开发者可以直接调用,无需从头训练,大大降低了开发门槛,魔搭社区提供了详细的文档、教程和示例代码,帮助开发者快速上手。同时,社区还支持在线调试和模型微调,方便开发者根据需求定制模型,魔搭社区汇聚了大量的AI开发者和研究者,大家可以在这里分享经验、交流技术,共同推动AI技术的发展。
总结
魔搭社区是一个强大的AI模型平台,每个模型的下载以及使用方式以及使用案例都为我们准备好了,为我们实现AI女友提供了丰富的技术支持和资源。通过魔搭社区,我们可以快速构建一个具备语音交互、自然语言理解和情感分析能力的AI女友。接下来,我们将结合这些技术,一步步实现我们的AI女友项目!
实现代码
ASR(SenseVoiceSmall)
为了适配更多的广大网友采用的是SenseVoiceSmall,SenseVoice多语言音频理解模型,支持语音识别、语种识别、语音情感识别、声学事件检测、逆文本正则化等能力,采用工业级数十万小时的标注音频进行模型训练,保证了模型的通用识别效果。模型可以被应用于中文、粤语、英语、日语、韩语音频识别,并输出带有情感和事件的富文本转写结果。
import os
from funasr import AutoModel
from modelscope import snapshot_download
class SpeechRecognizer:
def __init__(self, device="cuda"):
model_dir = snapshot_download( #模型下载
'iic/SenseVoiceSmall',
cache_dir="models/SenseVoiceSmall"
)
self.model = AutoModel( #模型初始化
model=model_dir,
trust_remote_code=True,
vad_model="fsmn-vad",
vad_kwargs={"max_single_segment_time": 30000},
device=device,
batch_size_s=60
)
def transcribe(self, audio_path): #调用
res = self.model.generate(
input=audio_path,
language="auto",
use_itn=True
)
return res[0]["text"] if res else ""LLM(Qwen2.5-0.5B-Instruct)
为了适配更多的广大网友采用的是Qwen2.5-0.5B-Instruct,Qwen2.5 是 Qwen 大型语言模型的最新系列。对于 Qwen2.5,我们发布了从 0.5 到 720 亿参数的基础语言模型和指令调优语言模型。
from modelscope import snapshot_download
from transformers import AutoModelForCausalLM, AutoTokenizer
import os
class ChatAssistant:
def __init__(self):
# 模型下载
model_dir = snapshot_download(
"Qwen/Qwen2.5-0.5B-Instruct",
cache_dir=os.path.join(os.path.dirname(os.path.dirname(__file__)), "models/Qwen2.5-0.5B-Instruct")
)
# 模型初始化
self.tokenizer = AutoTokenizer.from_pretrained(model_dir)
self.model = AutoModelForCausalLM.from_pretrained(
model_dir,
torch_dtype="auto", #自动选择数据类型
device_map="auto" #自动选择设备(cpu还是GPU)
)
def generate_response(self, prompt):
messages = [
{"role": "system", "content": "你的名字叫小恐龙,温柔体贴,喜欢用网络梗回答,回答简洁"}, #定义提示词
{"role": "user", "content": f"{prompt}(50字内回答)"}
]
inputs = self.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
model_inputs = self.tokenizer([inputs], return_tensors="pt").to(self.model.device)
outputs = self.model.generate(
**model_inputs,
max_new_tokens=100
)
return self.tokenizer.decode(outputs[0][len(model_inputs.input_ids[0]):], skip_special_tokens=True)
TTS(edge_tts)
import edge_tts
import asyncio
import os
import uuid
class VoiceSynthesizer:
def __init__(self, voice="zh-CN-XiaoyiNeural"):
self.voice = voice
async def synthesize(self, text):
# 生成唯一文件名,避免冲突
filename = f"response_{uuid.uuid4().hex}.mp3"
output_file = os.path.join("output", filename)
# 确保输出目录存在
os.makedirs("output", exist_ok=True)
# 使用上下文管理器确保资源释放
communicate = edge_tts.Communicate(text, self.voice)
await communicate.save(output_file)
return output_file
os.remove(output_file)
main
import os
import time
import numpy as np
import sounddevice as sd
from scipy.io.wavfile import write
import asyncio
from pynput import keyboard
import pygame
from modules.asr import SpeechRecognizer
from modules.llm import ChatAssistant
from modules.tts import VoiceSynthesizer
import torch
class VoiceAssistant:
def __init__(self):
# 初始化音频系统
pygame.mixer.init()
# 加载模型
self.recognizer = SpeechRecognizer(
device="cuda" if torch.cuda.is_available() else "cpu"
)
self.assistant = ChatAssistant()
self.tts = VoiceSynthesizer()
# 录音参数
self.sample_rate = 16000
self.is_recording = False
self.audio_data = []
# 键盘监听
self.listener = keyboard.Listener(
on_press=self._on_key_press,
on_release=self._on_key_release
)
self.listener.start()
def _on_key_press(self, key):
"""按下回车开始录音"""
if key == keyboard.Key.enter and not self.is_recording:
self._start_recording()
def _on_key_release(self, key):
"""松开回车停止录音"""
if key == keyboard.Key.enter and self.is_recording:
self._stop_recording()
def _start_recording(self):
"""启动录音"""
self.is_recording = True
self.audio_data = []
print("\n🎙️ 录音中...(松开回车结束)")
# 设置音频流
self.stream = sd.InputStream(
samplerate=self.sample_rate,
channels=1,
callback=self._audio_callback
)
self.stream.start()
def _audio_callback(self, indata, frames, time, status):
"""实时音频采集"""
if self.is_recording:
self.audio_data.append(indata.copy())
def _stop_recording(self):
"""停止录音并处理"""
self.stream.stop()
self.is_recording = False
print("🔄 处理中...")
try:
# 保存临时文件
audio = np.concatenate(self.audio_data, axis=0)
temp_file = "temp.wav"
write(temp_file, self.sample_rate, audio)
# 语音识别
text = self.recognizer.transcribe(temp_file)
print(f"\n🔊 识别结果:{text}")
if text:
# 生成回复
response = self.assistant.generate_response(text)
print(f"💡 生成回复:{response}")
# 语音合成
audio_file = asyncio.run(self.tts.synthesize(response))
print(f"✅ 合成文件:{audio_file}")
# 后台播放
self._play_audio(audio_file)
finally:
# 清理临时文件
if os.path.exists(temp_file):
os.remove(temp_file)
@staticmethod
def _play_audio(file_path):
"""后台静默播放"""
try:
pygame.mixer.music.load(file_path)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
time.sleep(0.1)
except Exception as e:
print(f"❌ 播放失败:{str(e)}")
if __name__ == "__main__":
assistant = VoiceAssistant()
print("="*50)
print("🗣️ 语音交互系统(按住回车录音,松开自动处理)")
print("="*50)
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
print("\n🛑 系统已安全退出")requirements.txt
# 核心依赖
torch>=2.0.0
torchaudio>=2.0.0
transformers>=4.30.0
numpy>=1.23.0
# ASR相关
funasr>=0.8.0
modelscope>=1.8.0
# 音频处理
sounddevice>=0.4.6
scipy>=1.10.0
librosa>=0.10.0
# TTS相关
edge-tts>=6.1.3
# 用户交互
pygame>=2.5.0
pynput>=1.7.6
# 工具类
tqdm>=4.65.0
asyncio>=3.4.3
accelerate目录结构
asr-llm-tts/
├── models/ # 预训练模型或自定义模型文件存放,目录代码会自动下载相关模型
├── modules/ # 核心功能模块
│ ├── __init__.py # 模块初始化文件
│ ├── asr.py # 自动语音识别(ASR)模块
│ ├── llm.py # 大型语言模型(LLM)交互模块
│ └── tts.py # 文本到语音(TTS)合成模块
├── output/ # 输出文件目录
├── temp/ # 临时文件目录(存储中间处理数据)
├── main.py # 主入口脚本(协调 ASR → LLM → TTS 流水线)
├── requirements.txt # 依赖库列表(如 torch, transformers)运行后结果:


师傅你好,想转载您的这篇文章。请问可以吗?