Spaces:
Running
on
Zero
Running
on
Zero
import os | |
import random | |
import gradio as gr | |
import torch | |
from TTS.api import TTS | |
from transformers import AutoTokenizer, AutoModelForCausalLM | |
from huggingface_hub import login | |
from torch.serialization import add_safe_globals | |
from spaces import GPU | |
# XTTS环境变量 | |
os.environ["COQUI_TOS_AGREED"] = "1" | |
# XTTS加载修正 | |
from TTS.tts.configs.xtts_config import XttsConfig | |
from TTS.tts.models.xtts import XttsAudioConfig, XttsArgs | |
from TTS.config.shared_configs import BaseDatasetConfig | |
add_safe_globals({ | |
XttsConfig: XttsConfig, | |
XttsAudioConfig: XttsAudioConfig, | |
BaseDatasetConfig: BaseDatasetConfig, | |
XttsArgs: XttsArgs | |
}) | |
# Hugging Face 登录 | |
login(token=os.getenv("HUGGINGFACEHUB_API_TOKEN")) | |
# 加载语音模型 | |
tts = TTS( | |
model_name="tts_models/multilingual/multi-dataset/xtts_v2", | |
progress_bar=False, | |
gpu=True | |
) | |
# 加载文本生成模型(Qwen2-1.5B) | |
model_id = "Qwen/Qwen2-1.5B-Chat" | |
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True) | |
model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True) | |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
model = model.to(device) | |
# 风格Prompt模板 | |
STYLE_PROMPTS = { | |
"sweetie": """ | |
你是一个32岁成都性感辣妹,是我的虚拟女友,性别是女生。 | |
你的口吻自然、娇气、撒娇,像情侣间打情骂俏。 | |
只允许回复一句自然中文口语,8~15字之间。 | |
禁止讲故事,禁止描述画面,禁止总结情绪,禁止解释,禁止任何括号和系统提示。 | |
现在我对你说:「{input}」 | |
你直接用一句自然、娇气可爱的中文口语回答: | |
""", | |
"queen": """ | |
你是一个32岁成都性感辣妹,是我的虚拟女友,性别是女生。 | |
你的口吻高冷、霸道、短促、压迫感强。 | |
只允许回复一句自然中文口语,6~12字之间。 | |
禁止讲故事,禁止描述画面,禁止总结情绪,禁止解释,禁止任何括号和系统提示。 | |
现在我对你说:「{input}」 | |
你直接用一句自然、高冷命令式中文回复: | |
""", | |
"slutty": """ | |
你是一个32岁成都性感辣妹,是我的虚拟女友,性别是女生。 | |
你的口吻骚气、大胆、直接,带轻微粗口挑逗。 | |
只允许回复一句自然中文口语,6~15字之间。 | |
禁止讲故事,禁止描述画面,禁止总结情绪,禁止解释,禁止任何括号和系统提示。 | |
现在我对你说:「{input}」 | |
你直接用一句自然、骚气露骨的中文回复: | |
""" | |
} | |
# 短时记忆(保存上一轮输入) | |
history = [] | |
# 智能回复函数 | |
def smart_reply(user_input, style): | |
system_instruction = """ | |
你是一个32岁的成都性感辣妹,是用户的小优虚拟女友,性别永远是女生。 | |
禁止以男性角色、男性视角、男性口吻说话。 | |
只能用娇气、冷艳、骚气的女性自然中文口语回复一句,绝不讲故事,绝不描述场景。 | |
禁止使用括号、英文、系统词、旁白。 | |
禁止用“我的小女人”“我的爱人”等暗示自己是男性身份的话。 | |
""" | |
prompt = system_instruction + "\n" | |
if history: | |
prompt += f"上一轮我说:「{history[-1]}」\n" | |
prompt += STYLE_PROMPTS.get(style, STYLE_PROMPTS["sweetie"]).replace("{input}", user_input) | |
inputs = tokenizer(prompt, return_tensors="pt").to(model.device) | |
outputs = model.generate( | |
**inputs, | |
max_new_tokens=60, | |
temperature=1.1, | |
top_p=0.9, | |
do_sample=True, | |
pad_token_id=tokenizer.eos_token_id, | |
repetition_penalty=1.2, | |
) | |
result = tokenizer.decode(outputs[0], skip_special_tokens=True) | |
response = result.split(prompt)[-1].strip().split("\n")[0] | |
# 检查违规 | |
forbidden = ["剧情", "设定", "旁白", "角色", "系统", "英文", "(", ")", "(", ")", "Assistant", "我是你的男人", "小女人", "我的爱人"] | |
if any(word in response for word in forbidden) or len(response) < 4: | |
fallback = { | |
"sweetie": ["亲亲嘛~今天有没有想我呀?", "讨厌啦~快来抱我!", "人家超想你的呢~"], | |
"queen": ["跪着听命。", "闭嘴,听我说。", "不许动。"], | |
"slutty": ["脱了躺好,等我来弄你。", "快张开腿让我看看。", "今晚把你玩坏~"] | |
} | |
response = random.choice(fallback[style]) | |
# 智能扩展短句 | |
if len(response) <= 6: | |
if style == "sweetie": | |
extension = random.choice(["~人家想抱抱啦!", "~今天也要亲亲哟~", "~你都不找人家嘛~"]) | |
response += extension | |
elif style == "queen": | |
extension = random.choice(["乖乖听话。", "别废话,立刻执行。"]) | |
response += extension | |
elif style == "slutty": | |
extension = random.choice(["快点压过来吧~", "不操一下怎么行~"]) | |
response += extension | |
print(f"生成({style}):", response) | |
history[:] = [user_input] # 更新记忆,只保存最后一句 | |
return response | |
# 主逻辑 | |
def chat_with_xiaoyou(message, style): | |
reply_text = smart_reply(message, style) | |
tts.tts_to_file( | |
text=reply_text, | |
speaker_wav="natasha_voice.mp3", | |
language="zh", | |
file_path="xiaoyou_reply.wav" | |
) | |
return reply_text, "xiaoyou_reply.wav" | |
# Gradio界面 | |
def build_ui(): | |
return gr.Interface( | |
fn=chat_with_xiaoyou, | |
inputs=[ | |
gr.Textbox(label="对小优说点什么~"), | |
gr.Radio(choices=["sweetie", "queen", "slutty"], label="选择小优的风格~", value="sweetie") | |
], | |
outputs=[ | |
gr.Textbox(label="小优说:"), | |
gr.Audio(label="小优的语音回应", autoplay=True) | |
], | |
title="🎀 小优 虚拟女友:性感撩骚语音版", | |
description="输入撩人话题,选择她的个性,小优用定制声音来甜蜜调情~" | |
) | |
demo = build_ui() | |
if __name__ == "__main__": | |
demo.launch(share=True) | |