| from transformers import ( |
| AutoTokenizer, |
| AutoModelForCausalLM, |
| BitsAndBytesConfig |
| ) |
| from peft import PeftModel |
| import torch |
| import gradio as gr |
| import os |
|
|
| |
| BASE_MODEL_NAME = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" |
| ADAPTER_PATH = "./" |
|
|
| print("🚀 正在加载基础模型...") |
|
|
| |
| model = AutoModelForCausalLM.from_pretrained( |
| BASE_MODEL_NAME, |
| torch_dtype=torch.float16, |
| device_map="cpu", |
| trust_remote_code=False, |
| ) |
|
|
| print("🔧 正在加载 LoRA 适配器...") |
|
|
| |
| model = PeftModel.from_pretrained(model, ADAPTER_PATH) |
| model.eval() |
|
|
| print("🔤 正在加载分词器...") |
| tokenizer = AutoTokenizer.from_pretrained(ADAPTER_PATH) |
| if tokenizer.pad_token is None: |
| tokenizer.pad_token = tokenizer.eos_token |
|
|
| |
| def generate_response(prompt: str, history=None): |
| try: |
| |
| input_text = prompt.strip() |
| |
| inputs = tokenizer( |
| input_text, |
| return_tensors="pt", |
| truncation=True, |
| max_length=256, |
| padding=True |
| ).to("cpu") |
| |
| with torch.no_grad(): |
| outputs = model.generate( |
| **inputs, |
| max_new_tokens=128, |
| do_sample=True, |
| temperature=0.7, |
| top_p=0.9, |
| pad_token_id=tokenizer.pad_token_id, |
| eos_token_id=tokenizer.eos_token_id, |
| ) |
| |
| response = tokenizer.decode(outputs[0], skip_special_tokens=True) |
| |
| if response.startswith(input_text): |
| response = response[len(input_text):].strip() |
| |
| return response or "抱歉,我无法回答这个问题。" |
| |
| except Exception as e: |
| return f"❌ 推理出错: {str(e)}" |
|
|
| |
| with gr.Blocks(title="冯氏家谱助手") as demo: |
| gr.Markdown("# 🧬 冯氏家族知识问答\n基于 TinyLlama 微调的家谱 AI 助手") |
| chatbot = gr.ChatInterface( |
| fn=generate_response, |
| examples=["冯国璋的字辈是什么?", "冯玉祥生于哪一年?", "冯家第几代是‘国’字辈?"], |
| title="冯氏家谱助手" |
| ) |
|
|
| |
| demo.launch() |