Spaces:
Sleeping
Sleeping
# app.py | |
import os | |
import json | |
import torch | |
import gradio as gr | |
from huggingface_hub import login | |
from pinecone import Pinecone | |
from sentence_transformers import SentenceTransformer | |
from transformers import AutoTokenizer, AutoModelForCausalLM | |
# 🔐 خواندن سکرتها | |
PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY") | |
PINECONE_INDEX_NAME = os.environ.get("INDEX_NAME", "tiyam-chat") | |
HF_TOKEN = os.environ.get("HF_TOKEN") | |
if not HF_TOKEN: | |
raise ValueError("❌ سکرت HF_TOKEN یافت نشد. لطفاً آن را در Settings > Secrets ثبت کنید.") | |
# 🔐 ورود به Hugging Face برای استفاده از مدل خصوصی | |
login(token=HF_TOKEN) | |
# 🔹 بارگذاری مدل embedding | |
embedding_model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2') | |
# 🔹 بارگذاری دادههای اولیه (اختیاری) | |
with open("tiyam_qa_data.json", "r", encoding="utf-8") as f: | |
data = json.load(f) | |
# 🔹 اتصال به Pinecone | |
pc = Pinecone(api_key=PINECONE_API_KEY) | |
index = pc.Index(PINECONE_INDEX_NAME) | |
# 🔹 بارگذاری مدل بازنویسی GEMMA | |
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2b-it", token=HF_TOKEN) | |
model = AutoModelForCausalLM.from_pretrained("google/gemma-2b-it", token=HF_TOKEN) | |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
model = model.to(device) | |
# 🔍 بازیابی پاسخ اولیه از Pinecone | |
def retrieve_answer(query, threshold=0.65, top_k=3): | |
query_embedding = embedding_model.encode([query])[0] | |
result = index.query(vector=query_embedding.tolist(), top_k=top_k, include_metadata=True) | |
if result['matches'] and result['matches'][0]['score'] > threshold: | |
metadata = result['matches'][0]['metadata'] | |
return metadata.get('answer', 'پاسخ یافت نشد') | |
else: | |
return "متأسفم، پاسخ دقیقی برای این سوال نداریم. لطفاً با ما تماس بگیرید." | |
# 🧠 بازنویسی پاسخ با تعیین هوشمند تعداد توکنها | |
def rewrite_answer(question, retrieved_answer): | |
prompt = f"""سؤال: {question} | |
پاسخ اولیه: {retrieved_answer} | |
پاسخ نهایی را به زبان طبیعی، حرفهای و دوستانه بازنویسی کن:""" | |
# 🔍 تعیین طول هوشمندانه توکن خروجی | |
base_len = len(retrieved_answer) | |
if base_len < 60: | |
max_tokens = 64 | |
elif base_len < 150: | |
max_tokens = 96 | |
else: | |
max_tokens = 128 | |
inputs = tokenizer(prompt, return_tensors="pt").to(device) | |
outputs = model.generate( | |
**inputs, | |
max_new_tokens=max_tokens, | |
temperature=0.7, | |
do_sample=True, | |
top_p=0.9 | |
) | |
final_answer = tokenizer.decode(outputs[0], skip_special_tokens=True) | |
return final_answer.replace(prompt, "").strip() | |
# 🧪 تابع نهایی چت | |
def chat_interface(question): | |
print("📥 سوال دریافت شد:", question) | |
raw_answer = retrieve_answer(question) | |
print("📤 پاسخ خام از Pinecone:", raw_answer) | |
final_answer = rewrite_answer(question, raw_answer) | |
print("✅ پاسخ نهایی بازنویسیشده:", final_answer) | |
return final_answer | |
# 🌐 رابط کاربری Gradio | |
demo = gr.Interface( | |
fn=chat_interface, | |
inputs="text", | |
outputs="text", | |
title="💬 چتبات هوشمند تیام", | |
description="سؤالات خود درباره خدمات بازاریابی دیجیتال تیام را بپرسید." | |
) | |
demo.launch() | |