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 ) # ---------- پردازش فایل‌ها با کش و موازی ---------- 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 # all_sentences = load_and_process_documents(folder_path) # st.markdown(all_sentences[2]) # ---------- ورودی جستجو ---------- 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 nltk from nltk.corpus import stopwords from nltk.tokenize import word_tokenize import string # تابع برای استخراج کلمات کلیدی از سوال def extract_keywords(query): # حذف علامت‌های نگارشی از جمله query = query.translate(str.maketrans('', '', string.punctuation)) # اگر برای اولین بار از nltk استفاده می‌کنید، باید این‌ها را دانلود کنید nltk.download('punkt') nltk.download('stopwords') words = word_tokenize(query) # حذف کلمات بی‌محتوا (Stopwords) stop_words = set(stopwords.words('persian')) # برای زبان فارسی، stopwords مربوطه باید تنظیم شود keywords = [word for word in words if word not in stop_words] return keywords # حالا کد شما به شکل زیر تغییر می‌کند: if query: threshold = 60 matched_sentences = [] # استخراج کلمات کلیدی از سوال keywords = extract_keywords(query) # پیدا کردن جملات مشابه for idx, sentence in enumerate(all_sentences): similarity = fuzz.partial_ratio(query, sentence) if similarity >= threshold: matched_sentences.append(sentence) if matched_sentences: found_sentences = [] # برای هر جمله در matched_sentences بررسی می‌کنیم که آیا کلمات کلیدی در آن وجود دارد یا نه for sentence in matched_sentences: if any(keyword in sentence for keyword in keywords): found_sentences.append(sentence) if found_sentences: # ایجاد متن نهایی از جملات مرتبط matched_text = "\n".join(found_sentences) # ساخت پرامپت اصلی برای تولید پاسخ نهایی حرفه‌ای prompt = f""" تعدادی پاسخ برای سوال زیر تولید شده است. لطفاً ابتدا این پاسخ‌ها را بررسی کن، سپس با در نظر گرفتن محتوای سوال و لحن آن، یک پاسخ نهایی حرفه‌ای، دقیق و روان از داخل پاسخ‌ها ارائه کن که هم به سوال پاسخ دهد و هم از نظر نگارشی و ساختاری در سطح بالایی باشد. پاسخ نهایی باید حداکثر 2048 کاراکتر و حداقل 512 باشد، خلاصه و واضح نوشته شود و فقط به زبان فارسی باشد. از تکرار اضافی پرهیز کن و فقط از پاسخ‌های زیر استفاده کن. در صورت نیاز، محتوای چند پاسخ را با هم ترکیب کن. سوال: {query} پاسخ‌ها: {matched_text} پاسخ نهایی حرفه‌ای بازنویسی‌شده: """ response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt) ]) rewritten = 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: rewritten = clean_text(rewritten) 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: # اگر هیچ جمله‌ای که کلمات کلیدی داشته باشد پیدا نشد prompt = f""" لطفاً برای سوال زیر یک متن مرتبط و معتبر تولید کن. اگر اطلاعات کافی وجود ندارد، صادقانه اعلام کن. فقط به زبان فارسی پاسخ بده: سوال: {query} """ response = llm([ SystemMessage(content="You are a helpful assistant."), HumanMessage(content=prompt) ]) rewritten = clean_text(response.content.strip()) st.markdown(f'
{rewritten}
', unsafe_allow_html=True) think.empty()