import streamlit as st from hazm import Normalizer, SentenceTokenizer import os import docx from langchain.chat_models import ChatOpenAI from langchain.schema import SystemMessage, HumanMessage from rapidfuzz import fuzz import concurrent.futures import time # from sentence_transformers import SentenceTransformer import numpy as np from hazm import * import re import nltk nltk.download('punkt') st.markdown(""" """, unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) # ---------- احراز هویت ---------- if "authenticated" not in st.session_state: st.session_state.authenticated = False if not st.session_state.authenticated: st.markdown('', unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) username = st.text_input("نام کاربری:", placeholder="شناسه خود را وارد کنید", label_visibility="visible") password = st.text_input("رمز عبور:", placeholder="رمز عبور ", type="password", label_visibility="visible") st.markdown(""" """, unsafe_allow_html=True) if st.button("ورود"): if username == "admin" and password == "123": st.session_state.authenticated = True st.rerun() else: st.markdown("""
نام کاربری یا رمز عبور اشتباه است.
""", unsafe_allow_html=True) st.stop() # ---------- سایدبار ---------- with st.sidebar: st.image("log.png", use_container_width=True) menu_items = [ ("گزارش عملیاتی", "https://cdn-icons-png.flaticon.com/512/3596/3596165.png", "https://m17idd-reporting.hf.space"), ("تاریخچه ماموریت‌ها", "https://cdn-icons-png.flaticon.com/512/709/709496.png", None), ("تحلیل داده‌های نظامی", "https://cdn-icons-png.flaticon.com/512/1828/1828932.png", "https://m17idd-test.hf.space"), ("مدیریت منابع", "https://cdn-icons-png.flaticon.com/512/681/681494.png", None), ("دستیار فرماندهی", "https://cdn-icons-png.flaticon.com/512/3601/3601646.png", None), ("تنظیمات امنیتی", "https://cdn-icons-png.flaticon.com/512/2099/2099058.png", None), ("پشتیبانی فنی", "https://cdn-icons-png.flaticon.com/512/597/597177.png", None), ] st.markdown(""" """, unsafe_allow_html=True) for idx, (text, icon, link) in enumerate(menu_items): content = f""" """ if link: content = f'{content}' st.markdown(content, unsafe_allow_html=True) if idx in [1, 3, 5]: st.markdown("
", unsafe_allow_html=True) st.markdown("""

رزم‌‌یار‌ارتش

دستیارهوشمندارتش جمهوری اسلامی ایران
""", unsafe_allow_html=True) # ---------- مدل زبانی ---------- llm = ChatOpenAI( base_url="https://api.together.xyz/v1", api_key='0291f33aee03412a47fa5d8e562e515182dcc5d9aac5a7fb5eefdd1759005979', model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free", max_tokens=1024 ) # ---------- ورودی جستجو ---------- st.markdown(""" """, unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) st.markdown(""" """, unsafe_allow_html=True) query = st.chat_input("چطور می‌تونم کمک کنم؟") if query: st.markdown(f'
{query}
', unsafe_allow_html=True) think = st.markdown("""

در حال فکر کردن...

""", unsafe_allow_html=True) else: st.markdown("") # استایل‌ها برای چرخش و پیام در حال فکر کردن st.markdown(""" """, unsafe_allow_html=True) import os import re import docx import streamlit as st import concurrent.futures from hazm import Normalizer from rapidfuzz import fuzz from langchain.schema import SystemMessage, HumanMessage folder_path = '46' normalizer = Normalizer() @st.cache_data(show_spinner="در حال پردازش اسناد... لطفاً صبور باشید.") def load_and_process_documents(path): def process_docx(filename): try: full_path = os.path.join(path, filename) doc = docx.Document(full_path) text = "\n".join([para.text for para in doc.paragraphs]) normalized = normalizer.normalize(text) return filename, normalized except Exception as e: print(f"Error processing {filename}: {e}") return filename, "" filenames = [f for f in os.listdir(path) if f.endswith(".docx")] doc_texts = {} with concurrent.futures.ThreadPoolExecutor() as executor: for filename, content in executor.map(process_docx, filenames): doc_texts[filename] = content return doc_texts doc_texts = load_and_process_documents(folder_path) def clean_text(text): return re.sub(r'[^آ-ی۰-۹0-9،.؟!؛+\-* ]+', '', text) def find_closest_filenames(query, filenames, top_n=3): scores = [(f, fuzz.partial_ratio(query, f)) for f in filenames] scores.sort(key=lambda x: x[1], reverse=True) return [score[0] for score in scores[:top_n]] from transformers import pipeline def summarize_text(text): summarizer = pipeline("summarization", model="facebook/bart-large-cnn") summary = summarizer(text, max_length=1024, min_length=512, do_sample=False) return summary[0]['summary_text'] def find_best_answer(query, top_files, doc_texts): best_match = None best_score = 0 best_text = "" for filename in top_files: text = doc_texts[filename] similarity = fuzz.partial_ratio(query, text) if similarity > best_score: best_score = similarity best_match = filename best_text = text # خلاصه کردن متن برای خروجی بهتر if best_text: summary = summarize_text(best_text) else: summary = "متنی برای خلاصه‌سازی پیدا نشد." return summary # حالا این رو در کد اصلی استفاده می‌کنیم: if query: # مرحله 1: درخواست از مدل برای بررسی وجود پاسخ در نام فایل‌ها top_files = find_closest_filenames(query, list(doc_texts.keys()), top_n=3) best_file, matched_text = find_best_answer(query, top_files, doc_texts) if best_file: # اگر پاسخ از اسم فایل‌ها پیدا شد prompt_for_model_1 = f""" لطفاً با توجه به سوال زیر و محتوای سند موجود، یک پاسخ نهایی حرفه‌ای، دقیق و روان تولید کن. فقط از متن سند استفاده کن. اگر اطلاعات کافی در متن وجود ندارد، صادقانه اعلام کن. سوال: {query} محتوای سند: {matched_text} پاسخ نهایی: """ response_model_1 = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt_for_model_1) ]) rewritten = clean_text(response_model_1.content.strip()) # مرحله 2: بررسی پاسخ مدل اول prompt_for_model_2 = f""" سوال: {query} آیا مدل اول به درستی جواب داده است؟ پاسخ مدل اول: {rewritten} لطفاً تایید کن که آیا این پاسخ مناسب است یا خیر. اگر مناسب نیست، لطفاً اطلاعات بیشتری از متن موجود در سند بده. """ response_model_2 = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt_for_model_2) ]) answer_model_2 = clean_text(response_model_2.content.strip()) if "تایید" in answer_model_2: # اگر تایید شد که پاسخ درست است st.markdown(f'
{rewritten}
', unsafe_allow_html=True) else: # مرحله 3: جستجو در متن کل سندها best_file_from_text = None best_answer_from_text = "" top_files_for_text = find_closest_filenames(query, list(doc_texts.keys()), top_n=3) for filename in top_files_for_text: text = doc_texts[filename] similarity = fuzz.partial_ratio(query, text) if similarity > 50: # حداقل شباهت برای انتخاب پاسخ best_file_from_text = filename best_answer_from_text = text break # اگر جواب خوبی پیدا شد، جستجو را متوقف می‌کنیم if best_file_from_text: # اگر جوابی از متن پیدا شد prompt_for_model_3 = f""" لطفاً با توجه به سوال زیر و محتوای سند موجود، یک پاسخ نهایی حرفه‌ای، دقیق و روان تولید کن. فقط از متن سند استفاده کن. اگر اطلاعات کافی در متن وجود ندارد، صادقانه اعلام کن. سوال: {query} محتوای سند: {best_answer_from_text} پاسخ نهایی: """ response_model_3 = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt_for_model_3) ]) rewritten_model_3 = clean_text(response_model_3.content.strip()) # بررسی تایید مدل 2 prompt_for_model_4 = f""" سوال: {query} آیا مدل دوم به درستی جواب داده است؟ پاسخ مدل دوم: {rewritten_model_3} لطفاً تایید کن که آیا این پاسخ مناسب است یا خیر. """ response_model_4 = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt_for_model_4) ]) answer_model_4 = clean_text(response_model_4.content.strip()) if "تایید" in answer_model_4: # اگر تایید شد که پاسخ درست است st.markdown(f'
{rewritten_model_3}
', unsafe_allow_html=True) else: # مرحله آخر: اگر تایید نشده بود، از دانش خود مدل استفاده کن prompt_for_model_5 = f""" سوال: {query} لطفاً جواب دقیقی از دانش خودت بده. """ response_model_5 = llm([ SystemMessage(content="You are a knowledgeable assistant."), HumanMessage(content=prompt_for_model_5) ]) rewritten_model_5 = clean_text(response_model_5.content.strip()) st.markdown(f'
{rewritten_model_5}
', unsafe_allow_html=True)