Younes13 commited on
Commit
4b84e82
·
verified ·
1 Parent(s): 06ffd21

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -28
app.py CHANGED
@@ -1,54 +1,196 @@
1
  import torch
2
- from transformers import AutoTokenizer, AutoModel
3
  import numpy as np
4
  from sklearn.metrics.pairwise import cosine_similarity
5
  import gradio as gr
 
6
 
7
- # 📌 مدل و توکنایزر
8
- model_name = "HooshvareLab/bert-fa-base-uncased"
9
- tokenizer = AutoTokenizer.from_pretrained(model_name)
10
- model = AutoModel.from_pretrained(model_name)
 
11
 
12
- # 📄 دیتاست اولیه (FAQ)
 
 
 
 
 
 
 
 
 
 
 
13
  faq_data = {
14
- "پایتخت ایران کجاست؟": "تهران",
15
- "زبان رسمی ایران چیست؟": "فارسی",
16
- "واحد پول ایران چیست؟": "ریال",
17
- "چه زمانی انتخاب واحد شروع می‌شود؟": "معمولاً پایان شهریور یا بهمن.",
18
- "چه معدلی برای گرفتن 24 واحد لازم است؟": "حداقل معدل 17.",
 
 
 
 
 
 
 
 
 
 
 
 
19
  }
20
 
21
- questions = list(faq_data.keys())
22
- answers = list(faq_data.values())
 
 
23
 
24
  # 📄 تولید embedding
25
  def get_embedding(text):
26
- inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=64)
27
  with torch.no_grad():
28
- outputs = model(**inputs)
29
- emb = outputs.last_hidden_state.mean(dim=1).squeeze().cpu().numpy()
30
  return emb
31
 
 
32
  faq_embeddings = [get_embedding(q) for q in questions]
33
 
34
- # 📄 تابع پاسخ
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  def answer_question(user_question):
 
 
 
 
 
 
 
 
 
 
36
  user_emb = get_embedding(user_question)
37
  sims = [cosine_similarity([user_emb], [emb])[0][0] for emb in faq_embeddings]
38
  best_idx = int(np.argmax(sims))
39
  best_score = sims[best_idx]
40
-
41
- if best_score > 0.7:
 
 
 
 
 
 
42
  return answers[best_idx]
43
  else:
44
- return "متأسفم، جواب دقیقی در دیتاست پیدا نکردم."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  # 📄 رابط Gradio
47
- with gr.Blocks() as demo:
48
- gr.Markdown("## 🤖 دستیار فارسی (پایه بر اساس semantic search با BERT)")
49
- inp = gr.Textbox(label="سؤال خود را بنویسید")
50
- out = gr.Textbox(label="پاسخ")
51
- btn = gr.Button("پاسخ بده")
52
- btn.click(fn=answer_question, inputs=inp, outputs=out)
53
-
54
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import torch
2
+ from transformers import AutoTokenizer, AutoModel, AutoModelForCausalLM
3
  import numpy as np
4
  from sklearn.metrics.pairwise import cosine_similarity
5
  import gradio as gr
6
+ import re
7
 
8
+ # 📌 مدل‌های مختلف
9
+ # مدل BERT برای semantic search
10
+ bert_model_name = "HooshvareLab/bert-fa-base-uncased"
11
+ bert_tokenizer = AutoTokenizer.from_pretrained(bert_model_name)
12
+ bert_model = AutoModel.from_pretrained(bert_model_name)
13
 
14
+ # مدل generative برای تولید پاسخ (می‌توانید از مدل‌های دیگر استفاده کنید)
15
+ # اگر مدل generative فارسی در دسترس نداشته باشید، از همین BERT استفاده می‌کنیم
16
+ try:
17
+ # مثال: استفاده از مدل generative فارسی
18
+ gen_model_name = "HooshvareLab/bert-fa-base-uncased" # جایگزین کنید
19
+ gen_tokenizer = AutoTokenizer.from_pretrained(gen_model_name)
20
+ gen_model = AutoModel.from_pretrained(gen_model_name)
21
+ has_generative = False # فعلاً False چون BERT generative نیست
22
+ except:
23
+ has_generative = False
24
+
25
+ # 📄 دیتاست گسترده‌تر
26
  faq_data = {
27
+ "پایتخت ایران کجاست؟": "تهران پایتخت ایران است.",
28
+ "زبان رسمی ایران چیست؟": "فارسی زبان رسمی ایران است.",
29
+ "واحد پول ایران چیست؟": "ریال واحد پول ایران است.",
30
+ "چه زمانی انتخاب واحد شروع می‌شود؟": "معمولاً انتخاب واحد در پایان شهریور یا بهمن ماه شروع می‌شود.",
31
+ "چه معدلی برای گرفتن 24 واحد لازم است؟": "برای گرفتن 24 واحد حداقل معدل 17 لازم است.",
32
+ "ساعت کاری ادارات چیست؟": "ساعت کاری ادارات معمولاً از 8 صبح تا 4 عصر است.",
33
+ "چگونه می‌توانم درخواست پاسپورت بدهم؟": "برای درخواست پاسپورت باید به اداره گذرنامه مراجعه کنید.",
34
+ "فصل‌های سال در ایران چیست؟": "فصل‌های سال شامل بهار، تابستان، پاییز و زمستان است.",
35
+ }
36
+
37
+ # اضافه کردن دانش عمومی
38
+ general_knowledge = {
39
+ "چگونه": "این سوال درباره نحوه انجام کاری است. برای پاسخ دقیق‌تر، لطفاً سوال خود را کامل‌تر بپرسید.",
40
+ "چرا": "این سوال درباره دلیل چیزی است. برای پاسخ بهتر، موضوع مشخصی را بیان کنید.",
41
+ "چیست": "این سوال تعریف چیزی را می‌خواهد. لطفاً موضوع مورد نظر را دقیق‌تر بیان کنید.",
42
+ "کجا": "این سوال درباره مکان است. برای پاسخ دقیق‌تر، موضوع خاصی را مشخص کنید.",
43
+ "کی": "این سوال درباره زمان است. لطفاً موضوع مورد نظر را دقیق‌تر بیان کنید.",
44
  }
45
 
46
+ # ترکیب دیتاست‌ها
47
+ all_data = {**faq_data, **general_knowledge}
48
+ questions = list(all_data.keys())
49
+ answers = list(all_data.values())
50
 
51
  # 📄 تولید embedding
52
  def get_embedding(text):
53
+ inputs = bert_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=128)
54
  with torch.no_grad():
55
+ outputs = bert_model(**inputs)
56
+ emb = outputs.last_hidden_state.mean(dim=1).squeeze().cpu().numpy()
57
  return emb
58
 
59
+ # محاسبه embedding برای همه سوالات
60
  faq_embeddings = [get_embedding(q) for q in questions]
61
 
62
+ # 📄 تشخیص نوع سوال
63
+ def detect_question_type(question):
64
+ question_lower = question.lower()
65
+
66
+ # الگوهای سوال
67
+ patterns = {
68
+ 'definition': ['چیست', 'چی هست', 'تعریف', 'معنی'],
69
+ 'how': ['چگونه', 'چطور', 'چه طور'],
70
+ 'why': ['چرا', 'به چه دلیل'],
71
+ 'when': ['چه زمانی', 'کی', 'چه وقت'],
72
+ 'where': ['کجا', 'در کجا', 'کدام مکان'],
73
+ 'who': ['کی', 'چه کسی', 'کدام فرد'],
74
+ 'greeting': ['سلام', 'درود', 'صبح بخیر', 'ظهر بخیر', 'عصر بخیر', 'شب بخیر'],
75
+ 'thanks': ['ممنون', 'متشکرم', 'سپاس', 'تشکر'],
76
+ 'yes_no': ['آیا', 'مگر', 'آیا که']
77
+ }
78
+
79
+ for q_type, words in patterns.items():
80
+ for word in words:
81
+ if word in question_lower:
82
+ return q_type
83
+
84
+ return 'general'
85
+
86
+ # 📄 تولید پاسخ برای سوالات عمومی
87
+ def generate_general_answer(question, question_type):
88
+ if question_type == 'greeting':
89
+ return "سلام! چطور می‌تونم کمکتون کنم؟"
90
+
91
+ elif question_type == 'thanks':
92
+ return "خواهش می‌کنم! اگر سوال دیگری دارید، بپرسید."
93
+
94
+ elif question_type == 'definition':
95
+ return "برای تعریف دقیق‌تر این موضوع، لطفاً سوال خود را کامل‌تر بپرسید تا بتوانم پاسخ مناسبی ارائه دهم."
96
+
97
+ elif question_type == 'how':
98
+ return "برای راهنمایی دقیق‌تر درباره نحوه انجام این کار، لطفاً جزئیات بیشتری از سوال خود ارائه دهید."
99
+
100
+ elif question_type == 'why':
101
+ return "برای توضیح دلایل، لطفاً موضوع مورد نظر را دقیق‌تر مشخص کنید تا بتوانم پاسخ مناسبی ارائه دهم."
102
+
103
+ elif question_type == 'when':
104
+ return "برای اطلاع از زمان دقیق، لطفاً موضوع خاصی را مشخص کنید تا بتوانم راهنمایی کنم."
105
+
106
+ elif question_type == 'where':
107
+ return "برای اطلاع از مکان، لطفاً موضوع مورد نظر را دقیق‌تر بیان کنید."
108
+
109
+ elif question_type == 'yes_no':
110
+ return "برای پاسخ به این سوال، لطفاً موضوع را کامل‌تر مطرح کنید."
111
+
112
+ else:
113
+ # پاسخ عمومی هوشمند
114
+ return "سوال جالبی پرسیده‌اید. متأسفانه در حال حاضر اطلاعات کاملی در این زمینه ندارم، اما اگر سوال خود را دقیق‌تر مطرح کنید، شاید بتوانم کمک بیشتری کنم."
115
+
116
+ # 📄 تابع اصلی پاسخ
117
  def answer_question(user_question):
118
+ # حذف فاصله‌های اضافی
119
+ user_question = user_question.strip()
120
+
121
+ if not user_question:
122
+ return "لطفاً سوال خود را بنویسید."
123
+
124
+ # تشخیص نوع سوال
125
+ question_type = detect_question_type(user_question)
126
+
127
+ # جستجوی semantic در دیتاست
128
  user_emb = get_embedding(user_question)
129
  sims = [cosine_similarity([user_emb], [emb])[0][0] for emb in faq_embeddings]
130
  best_idx = int(np.argmax(sims))
131
  best_score = sims[best_idx]
132
+
133
+ # تنظیم threshold بر اساس نوع سوال
134
+ if question_type in ['greeting', 'thanks']:
135
+ threshold = 0.3
136
+ else:
137
+ threshold = 0.65
138
+
139
+ if best_score > threshold:
140
  return answers[best_idx]
141
  else:
142
+ # تولید پاسخ برای سوالات خارج از دیتاست
143
+ return generate_general_answer(user_question, question_type)
144
+
145
+ # 📄 تابع اضافه کردن دانش جدید
146
+ def add_knowledge(question, answer):
147
+ if question and answer:
148
+ global questions, answers, faq_embeddings, all_data
149
+
150
+ # اضافه کردن به دیتاست
151
+ all_data[question] = answer
152
+ questions.append(question)
153
+ answers.append(answer)
154
+
155
+ # محاسبه embedding جدید
156
+ new_emb = get_embedding(question)
157
+ faq_embeddings.append(new_emb)
158
+
159
+ return f"دانش جدید اضافه شد: {question} -> {answer}"
160
+ else:
161
+ return "لطفاً هم سوال و هم پاسخ را وارد کنید."
162
 
163
  # 📄 رابط Gradio
164
+ with gr.Blocks(title="🤖 دستیار فارسی هوشمند") as demo:
165
+ gr.Markdown("## 🤖 دستیار فارسی هوشمند (پاسخ به سوالات داخل و خارج دیتاست)")
166
+
167
+ with gr.Tab("💬 پرسش و پاسخ"):
168
+ inp = gr.Textbox(label="سؤال خود را بنویسید", placeholder="مثال: سلام، پایتخت ایران کجاست؟")
169
+ out = gr.Textbox(label="��اسخ", lines=3)
170
+ btn = gr.Button("پاسخ بده", variant="primary")
171
+ btn.click(fn=answer_question, inputs=inp, outputs=out)
172
+
173
+ with gr.Tab("📚 افزودن دانش"):
174
+ gr.Markdown("### افزودن سوال و پاسخ جدید به دیتاست")
175
+ new_q = gr.Textbox(label="سوال جدید")
176
+ new_a = gr.Textbox(label="پاسخ جدید", lines=2)
177
+ add_btn = gr.Button("اضافه کن", variant="secondary")
178
+ add_result = gr.Textbox(label="نتیجه")
179
+ add_btn.click(fn=add_knowledge, inputs=[new_q, new_a], outputs=add_result)
180
+
181
+ with gr.Tab("ℹ️ راهنما"):
182
+ gr.Markdown("""
183
+ ### نحوه استفاده:
184
+ 1. **سوالات معمولی**: مثل "پایتخت ایران کجاست؟"
185
+ 2. **احوال‌پرسی**: مثل "سلام" یا "صبح بخیر"
186
+ 3. **تشکر**: مثل "ممنون" یا "متشکرم"
187
+ 4. **سوالات عمومی**: حتی اگر در دیتاست نباشد، پاسخ مناسب می‌دهد
188
+
189
+ ### ویژگی‌ها:
190
+ - پاسخ به سوالات داخل دیتاست با دقت بالا
191
+ - پاسخ هوشمند به سوالات خارج دیتاست
192
+ - تشخیص نوع سوال (تعریف، چگونه، چرا، کجا، کی)
193
+ - قابلیت افزودن دانش جدید
194
+ """)
195
+
196
+ demo.launch()