natasha-demo / app.py
ABSOLUTEUNB's picture
Update app.py
483bbce verified
raw
history blame contribute delete
6.07 kB
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 = []
# 智能回复函数
@GPU
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
# 主逻辑
@GPU
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)