File size: 3,611 Bytes
9ad95ef
0f5d2ed
 
9ad95ef
0f5d2ed
9ad95ef
8bb4acb
0f5d2ed
 
 
281c0ae
8bb4acb
0f5d2ed
 
 
74c93be
8bb4acb
 
0f5d2ed
d2af11c
8bb4acb
 
d2af11c
8bb4acb
 
d2af11c
9ad95ef
 
7291a91
0f5d2ed
 
 
 
d2af11c
0f5d2ed
 
 
 
be823ee
d2af11c
08f847c
0f5d2ed
f957bce
35e4839
f957bce
9ad95ef
 
f957bce
9ad95ef
7291a91
d2af11c
0f5d2ed
 
 
 
 
d2af11c
 
 
 
 
 
 
 
 
0f5d2ed
 
 
d2af11c
0f5d2ed
 
 
 
 
 
 
d2af11c
9ad95ef
d2af11c
0f5d2ed
d2af11c
0f5d2ed
d2af11c
0f5d2ed
f957bce
d2af11c
0f5d2ed
 
 
 
 
 
 
7291a91
84a7b0a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# 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()