Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -87,48 +87,72 @@ def create_vector_db(docs):
|
|
| 87 |
return None, f"خطا در پردازش وکتوری: {str(e)}"
|
| 88 |
|
| 89 |
def check_plagiarism(text):
|
| 90 |
-
# یه چک ساده با مقایسه متن با نتایج گوگل
|
| 91 |
try:
|
| 92 |
-
query = text[:100]
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
max_similarity = 0
|
| 98 |
-
for result in
|
| 99 |
similarity = SequenceMatcher(None, text[:500], result).ratio()
|
| 100 |
max_similarity = max(max_similarity, similarity)
|
| 101 |
-
|
|
|
|
|
|
|
| 102 |
except Exception as e:
|
| 103 |
logger.error(f"خطا در چک سرقت ادبی: {str(e)}")
|
| 104 |
return None
|
| 105 |
|
| 106 |
def suggest_resources(text):
|
| 107 |
-
# پیشنهاد منابع با جستجوی ساده در arXiv
|
| 108 |
try:
|
| 109 |
-
query = " ".join(text.split()[:5])
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
except Exception as e:
|
| 116 |
logger.error(f"خطا در پیشنهاد منابع: {str(e)}")
|
| 117 |
return ["خطا در جستجوی منابع"]
|
| 118 |
|
| 119 |
def evaluate_quality(docs):
|
| 120 |
-
# ارزیابی ساده کیفیت
|
| 121 |
text = " ".join([doc.page_content for doc in docs])
|
| 122 |
score = 0
|
| 123 |
if re.search(r"منابع|References|Bibliography", text, re.I):
|
| 124 |
-
score += 30
|
| 125 |
if len(text.split()) > 5000:
|
| 126 |
-
score += 30
|
| 127 |
if re.search(r"جدول|شکل|Table|Figure", text, re.I):
|
| 128 |
-
score += 20
|
| 129 |
if re.search(r"نتیجهگیری|Conclusion", text, re.I):
|
| 130 |
-
score += 20
|
| 131 |
-
return max(min(score, 100), 10)
|
| 132 |
|
| 133 |
llm_gemini = ChatGoogleGenerativeAI(model="gemini-pro", google_api_key=gemini_api_key, convert_system_message_to_human=True, temperature=0.5)
|
| 134 |
|
|
@@ -160,7 +184,7 @@ general_qa_prompt = PromptTemplate(
|
|
| 160 |
)
|
| 161 |
|
| 162 |
plagiarism_prompt = PromptTemplate(
|
| 163 |
-
template="""درصد تشابه متن زیر با منابع عمومی را گزارش دهید:
|
| 164 |
**متن:**
|
| 165 |
{context}
|
| 166 |
**نتیجه:** {similarity}%""",
|
|
@@ -228,7 +252,8 @@ def academic_chatbot(pdf_file, mode, query, language, detail_level, section_drop
|
|
| 228 |
try:
|
| 229 |
if mode == "خلاصه خودکار":
|
| 230 |
context = " ".join([doc.page_content for doc in docs])
|
| 231 |
-
|
|
|
|
| 232 |
elif mode == "چک سرقت ادبی":
|
| 233 |
context = " ".join([doc.page_content for doc in docs if section_dropdown == "کل سند" or doc in sections.get(section_dropdown, [])])
|
| 234 |
similarity = check_plagiarism(context)
|
|
@@ -237,7 +262,8 @@ def academic_chatbot(pdf_file, mode, query, language, detail_level, section_drop
|
|
| 237 |
context = " ".join([doc.page_content for doc in docs if section_dropdown == "کل سند" or doc in sections.get(section_dropdown, [])])
|
| 238 |
score = evaluate_quality(docs if section_dropdown == "کل سند" else sections.get(section_dropdown, []))
|
| 239 |
explanation = "امتیاز بر اساس وجود منابع، طول متن، جداول/شکلها و نتیجهگیری محاسبه شده است."
|
| 240 |
-
|
|
|
|
| 241 |
else:
|
| 242 |
result = chain.invoke({"question": query, "chat_history": []})["answer"]
|
| 243 |
|
|
@@ -248,6 +274,8 @@ def academic_chatbot(pdf_file, mode, query, language, detail_level, section_drop
|
|
| 248 |
return f"{result}\n\n⏱ زمان پردازش: {time.time() - start_time:.2f} ثانیه"
|
| 249 |
except Exception as e:
|
| 250 |
logger.error(f"خطا در پردازش: {str(e)}")
|
|
|
|
|
|
|
| 251 |
return f"خطا: {str(e)}"
|
| 252 |
|
| 253 |
with gr.Blocks(title="تحلیلگر حرفهای پایاننامه") as iface:
|
|
|
|
| 87 |
return None, f"خطا در پردازش وکتوری: {str(e)}"
|
| 88 |
|
| 89 |
def check_plagiarism(text):
|
|
|
|
| 90 |
try:
|
| 91 |
+
query = text[:100]
|
| 92 |
+
# جستجوی گوگل (جهانی)
|
| 93 |
+
url_global = f"https://www.google.com/search?q={query}"
|
| 94 |
+
response_global = requests.get(url_global, headers={"User-Agent": "Mozilla/5.0"})
|
| 95 |
+
soup_global = BeautifulSoup(response_global.text, 'html.parser')
|
| 96 |
+
results_global = [h.get_text() for h in soup_global.find_all('h3')[:3]]
|
| 97 |
+
|
| 98 |
+
# جستجوی گوگل با تنظیم فارسی
|
| 99 |
+
url_fa = f"https://www.google.com/search?q={query}&hl=fa"
|
| 100 |
+
response_fa = requests.get(url_fa, headers={"User-Agent": "Mozilla/5.0"})
|
| 101 |
+
soup_fa = BeautifulSoup(response_fa.text, 'html.parser')
|
| 102 |
+
results_fa = [h.get_text() for h in soup_fa.find_all('h3')[:3]]
|
| 103 |
+
|
| 104 |
+
# جستجو در SID.ir
|
| 105 |
+
url_sid = f"https://www.sid.ir/Fa/Journal/SearchPaper.aspx?str={query}"
|
| 106 |
+
response_sid = requests.get(url_sid, headers={"User-Agent": "Mozilla/5.0"})
|
| 107 |
+
soup_sid = BeautifulSoup(response_sid.text, 'html.parser')
|
| 108 |
+
results_sid = [item.get_text() for item in soup_sid.select('.title')[:3]] # عناوین مقالات
|
| 109 |
+
|
| 110 |
+
all_results = results_global + results_fa + results_sid
|
| 111 |
max_similarity = 0
|
| 112 |
+
for result in all_results:
|
| 113 |
similarity = SequenceMatcher(None, text[:500], result).ratio()
|
| 114 |
max_similarity = max(max_similarity, similarity)
|
| 115 |
+
|
| 116 |
+
time.sleep(1) # فاصله بین درخواستها برای جلوگیری از 429
|
| 117 |
+
return max_similarity * 100
|
| 118 |
except Exception as e:
|
| 119 |
logger.error(f"خطا در چک سرقت ادبی: {str(e)}")
|
| 120 |
return None
|
| 121 |
|
| 122 |
def suggest_resources(text):
|
|
|
|
| 123 |
try:
|
| 124 |
+
query = " ".join(text.split()[:5])
|
| 125 |
+
# arXiv
|
| 126 |
+
url_arxiv = f"https://arxiv.org/search/?query={query}&searchtype=all&source=header"
|
| 127 |
+
response_arxiv = requests.get(url_arxiv, headers={"User-Agent": "Mozilla/5.0"})
|
| 128 |
+
soup_arxiv = BeautifulSoup(response_arxiv.text, 'html.parser')
|
| 129 |
+
papers_arxiv = [paper.get_text().strip() for paper in soup_arxiv.find_all('p', class_='title')[:2]]
|
| 130 |
+
|
| 131 |
+
# SID.ir
|
| 132 |
+
url_sid = f"https://www.sid.ir/Fa/Journal/SearchPaper.aspx?str={query}"
|
| 133 |
+
response_sid = requests.get(url_sid, headers={"User-Agent": "Mozilla/5.0"})
|
| 134 |
+
soup_sid = BeautifulSoup(response_sid.text, 'html.parser')
|
| 135 |
+
papers_sid = [item.get_text().strip() for item in soup_sid.select('.title')[:2]]
|
| 136 |
+
|
| 137 |
+
resources = papers_arxiv + papers_sid if papers_sid else papers_arxiv
|
| 138 |
+
time.sleep(1) # فاصله برای جلوگیری از 429
|
| 139 |
+
return resources if resources else ["منبعی یافت نشد."]
|
| 140 |
except Exception as e:
|
| 141 |
logger.error(f"خطا در پیشنهاد منابع: {str(e)}")
|
| 142 |
return ["خطا در جستجوی منابع"]
|
| 143 |
|
| 144 |
def evaluate_quality(docs):
|
|
|
|
| 145 |
text = " ".join([doc.page_content for doc in docs])
|
| 146 |
score = 0
|
| 147 |
if re.search(r"منابع|References|Bibliography", text, re.I):
|
| 148 |
+
score += 30
|
| 149 |
if len(text.split()) > 5000:
|
| 150 |
+
score += 30
|
| 151 |
if re.search(r"جدول|شکل|Table|Figure", text, re.I):
|
| 152 |
+
score += 20
|
| 153 |
if re.search(r"نتیجهگیری|Conclusion", text, re.I):
|
| 154 |
+
score += 20
|
| 155 |
+
return max(min(score, 100), 10)
|
| 156 |
|
| 157 |
llm_gemini = ChatGoogleGenerativeAI(model="gemini-pro", google_api_key=gemini_api_key, convert_system_message_to_human=True, temperature=0.5)
|
| 158 |
|
|
|
|
| 184 |
)
|
| 185 |
|
| 186 |
plagiarism_prompt = PromptTemplate(
|
| 187 |
+
template="""درصد تشابه متن زیر با منابع عمومی و فارسی را گزارش دهید:
|
| 188 |
**متن:**
|
| 189 |
{context}
|
| 190 |
**نتیجه:** {similarity}%""",
|
|
|
|
| 252 |
try:
|
| 253 |
if mode == "خلاصه خودکار":
|
| 254 |
context = " ".join([doc.page_content for doc in docs])
|
| 255 |
+
time.sleep(2) # فاصله برای کاهش درخواستها
|
| 256 |
+
result = chain.invoke({"context": context[:5000]})["text"] # محدود کردن ورودی
|
| 257 |
elif mode == "چک سرقت ادبی":
|
| 258 |
context = " ".join([doc.page_content for doc in docs if section_dropdown == "کل سند" or doc in sections.get(section_dropdown, [])])
|
| 259 |
similarity = check_plagiarism(context)
|
|
|
|
| 262 |
context = " ".join([doc.page_content for doc in docs if section_dropdown == "کل سند" or doc in sections.get(section_dropdown, [])])
|
| 263 |
score = evaluate_quality(docs if section_dropdown == "کل سند" else sections.get(section_dropdown, []))
|
| 264 |
explanation = "امتیاز بر اساس وجود منابع، طول متن، جداول/شکلها و نتیجهگیری محاسبه شده است."
|
| 265 |
+
time.sleep(2) # فاصله برای کاهش درخواستها
|
| 266 |
+
result = chain.invoke({"context": context[:5000], "score": score, "explanation": explanation})["text"]
|
| 267 |
else:
|
| 268 |
result = chain.invoke({"question": query, "chat_history": []})["answer"]
|
| 269 |
|
|
|
|
| 274 |
return f"{result}\n\n⏱ زمان پردازش: {time.time() - start_time:.2f} ثانیه"
|
| 275 |
except Exception as e:
|
| 276 |
logger.error(f"خطا در پردازش: {str(e)}")
|
| 277 |
+
if "429" in str(e):
|
| 278 |
+
return "خطا: محدودیت درخواست به API Gemini. لطفاً چند دقیقه صبر کنید و دوباره امتحان کنید."
|
| 279 |
return f"خطا: {str(e)}"
|
| 280 |
|
| 281 |
with gr.Blocks(title="تحلیلگر حرفهای پایاننامه") as iface:
|