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) folder_path = '46' normalizer = Normalizer() sentence_tokenizer = SentenceTokenizer() @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) sentences = normalized return sentences except Exception as e: print(f"Error processing {filename}: {e}") return [] with concurrent.futures.ThreadPoolExecutor() as executor: results = executor.map(process_docx, [f for f in os.listdir(path) if f.endswith(".docx")]) return list(results) all_sentences = load_and_process_documents(folder_path) def clean_text(text): cleaned_text = re.sub(r'[^آ-ی۰-۹0-9،.؟!؛+\-* ]+', '', text) return cleaned_text def compute_similarity(sentence, query, threshold): similarity = fuzz.partial_ratio(sentence, query) if similarity >= threshold: return sentence return None import string from hazm import word_tokenize, sent_tokenize from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.cluster import KMeans from sklearn.metrics.pairwise import cosine_similarity from concurrent.futures import ThreadPoolExecutor # تابع خلاصه‌سازی متن با استفاده از KMeans def summarize_text_with_kmeans(text, num_sentences=3): sentences = sent_tokenize(text) # تقسیم متن به جملات tfidf_vectorizer = TfidfVectorizer() tfidf_matrix = tfidf_vectorizer.fit_transform(sentences) # تبدیل جملات به ماتریس TF-IDF # الگوریتم خوشه‌بندی KMeans kmeans = KMeans(n_clusters=1) # یک خوشه برای استخراج خلاصه kmeans.fit(tfidf_matrix) # پیدا کردن جملات نزدیک به مرکز خوشه closest_centroid = kmeans.cluster_centers_[0] similarities = cosine_similarity(tfidf_matrix, closest_centroid.reshape(1, -1)) similar_sentences_indices = similarities.flatten().argsort()[-num_sentences:][::-1] # انتخاب jملات نزدیک summary = [sentences[i] for i in similar_sentences_indices] return ' '.join(summary) # فرض بر این است که query و all_sentences قبلاً تعریف شده‌اند if query: threshold = 75 keywords = query # خلاصه‌سازی متن قبل از ارسال به LLM text_to_summarize = "\n".join(all_sentences) # تمام جملات را با هم ترکیب کنید summarized_text = summarize_text_with_kmeans(text_to_summarize) # استفاده از پردازش موازی برای افزایش سرعت fuzzy matching with ThreadPoolExecutor(max_workers=8) as executor: futures = [executor.submit(compute_similarity, sentence, query, threshold) for sentence in all_sentences] matched_sentences = [future.result() for future in futures if future.result()] if matched_sentences: found_sentences = [sentence for sentence in matched_sentences if any(keyword in sentence for keyword in keywords)] if found_sentences: matched_text = "\n".join(found_sentences) prompt = f""" تعدادی پاسخ برای سوال زیر تولید شده است. لطفاً ابتدا این پاسخ‌ها را بررسی کن، سپس با در نظر گرفتن محتوای سوال و لحن آن، یک پاسخ نهایی حرفه‌ای، دقیق و روان از داخل پاسخ‌ها ارائه کن که هم به سوال پاسخ دهد و هم از نظر نگارشی و ساختاری در سطح بالایی باشد. پاسخ نهایی باید حداکثر 2048 کاراکتر و حداقل 512 باشد، خلاصه و واضح نوشته شود و فقط به زبان فارسی باشد. از تکرار اضافی پرهیز کن و فقط از پاسخ‌های زیر استفاده کن. در صورت نیاز، محتوای چند پاسخ را با هم ترکیب کن. سوال: {query} پاسخ‌ها: {summarized_text} پاسخ نهایی حرفه‌ای بازنویسی‌شده: """ response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt) ]) rewritten = clean_text(response.content.strip()) review_prompt = f""" لطفاً بررسی کن که آیا پاسخ زیر به سوال داده‌شده مرتبط، دقیق و معتبر است یا خیر. اگر پاسخ قابل قبول و دقیق است بنویس 'تأیید شد'. اگر متوسط است بنویس 'کمی خوب'. اگر بی‌ربط یا اشتباه است بنویس 'نیاز به اصلاح دارد'. سوال: {query} پاسخ: {rewritten} """ review_response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=review_prompt) ]) review_result = review_response.content.strip() if "تأیید شد" in review_result: st.markdown(f'
{rewritten}
', unsafe_allow_html=True) elif "کمی خوب" in review_result: final_prompt = f""" لطفاً برای سوال زیر پاسخی حرفه‌ای، دقیق و روان تولید کن که مرتبط و معتبر باشد. از زبانی جز فارسی استفاده نکن. از محتوای زیر استفاده کن و یک پاسخ نهایی خوب بنویس: سوال: {query} پاسخ اولیه: {rewritten} پاسخ نهایی: """ new_response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=final_prompt) ]) final_answer = clean_text(new_response.content.strip()) st.markdown(f'
{final_answer}
', unsafe_allow_html=True) else: fallback_prompt = f""" لطفاً برای سوال زیر پاسخی حرفه‌ای، دقیق و روان تولید کن که مرتبط و معتبر باشد. اگر اطلاعات کافی وجود ندارد، صادقانه بگو. فقط به زبان فارسی پاسخ بده: سوال: {query} """ fallback_response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=fallback_prompt) ]) final_fallback = clean_text(fallback_response.content.strip()) st.markdown(f'
{final_fallback}
', unsafe_allow_html=True) else: fallback_prompt = f""" لطفاً برای سوال زیر یک متن مرتبط و معتبر تولید کن. اگر اطلاعات کافی وجود ندارد، صادقانه اعلام کن. فقط به زبان فارسی پاسخ بده: سوال: {query} """ response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=fallback_prompt) ]) rewritten = clean_text(response.content.strip()) st.markdown(f'
{rewritten}
', unsafe_allow_html=True) think.empty()