|
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 |
|
st.markdown(""" |
|
<style> |
|
/* استایل برای هدر */ |
|
.stAppHeader.st-emotion-cache-12fmjuu.e4hpqof0 { |
|
background-color: rgba(58, 83, 56, 0.9) !important; /* سبز متمایل به خاکی */ |
|
color: #d4d4d4 !important; /* رنگ متن روشن */ |
|
font-family: 'Vazirmatn', Tahoma, sans-serif !important; |
|
padding: 20px !important; /* فضای داخلی بیشتر */ |
|
border-radius: 10px !important; /* گوشههای گرد */ |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important; /* سایه برای برجسته شدن */ |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
st.markdown(""" |
|
<style> |
|
@font-face { |
|
font-family: 'Shabnam'; |
|
src: url('https://cdn.jsdelivr.net/gh/rastikerdar/shabnam-font/dist/Shabnam.woff2') format('woff2'), |
|
url('https://cdn.jsdelivr.net/gh/rastikerdar/shabnam-font/dist/Shabnam.woff') format('woff'); |
|
font-weight: 400; |
|
font-style: normal; |
|
} |
|
html, body, [class*="css"] { |
|
font-family: 'Shabnam', Tahoma, sans-serif !important; |
|
font-weight: 500 !important; |
|
direction: rtl; |
|
text-align: right; |
|
} |
|
.stApp { |
|
background: linear-gradient(to left, #4b5e40, #2e3b2e); |
|
color: #ffffff; |
|
} |
|
[data-testid="stSidebar"] { |
|
width: 260px !important; |
|
background-color: #1a2b1e; |
|
border: none !important; |
|
padding-top: 20px; |
|
} |
|
.menu-item { |
|
display: flex; |
|
align-items: center; |
|
gap: 12px; |
|
padding: 12px 20px; |
|
font-size: 16px; |
|
font-weight: 600; |
|
color: #d4d4d4; |
|
cursor: pointer; |
|
transition: background-color 0.3s ease; |
|
} |
|
.menu-item:hover { |
|
background-color: #2e3b2e; |
|
color: #b8860b; |
|
} |
|
.menu-item img { |
|
width: 24px; |
|
height: 24px; |
|
} |
|
.stButton>button { |
|
background-color: #b8860b !important; |
|
color: #1a2b1e !important; |
|
font-family: 'Shabnam', Tahoma; |
|
font-weight: 700 !important; |
|
border-radius: 10px; |
|
padding: 12px 24px; |
|
border: none; |
|
transition: all 0.3s ease; |
|
font-size: 16px; |
|
width: 100%; |
|
margin: 10px 0; |
|
} |
|
.stButton>button:hover { |
|
background-color: #8b6508 !important; |
|
transform: translateY(-2px); |
|
box-shadow: 0 4px 8px rgba(0,0,0,0.3); |
|
} |
|
.header-text { |
|
text-align: center; |
|
margin: 20px 0; |
|
background-color: rgba(26, 43, 30, 0.9); |
|
padding: 25px; |
|
border-radius: 15px; |
|
box-shadow: 0 6px 12px rgba(0,0,0,0.4); |
|
} |
|
.header-text h1 { |
|
font-size: 42px; |
|
color: #b8860b; |
|
margin: 0; |
|
font-weight: 800; |
|
} |
|
.subtitle { |
|
font-size: 18px; |
|
color: #d4d4d4; |
|
font-weight: 600; |
|
margin-top: 10px; |
|
} |
|
.chat-message { |
|
background-color: rgba(26, 43, 30, 0.95); |
|
border: 2px solid #b8860b; |
|
border-radius: 15px; |
|
padding: 20px; |
|
margin: 15px 0; |
|
box-shadow: 0 6px 12px rgba(0,0,0,0.3); |
|
animation: fadeIn 0.6s ease; |
|
font-size: 18px; |
|
color: #d4d4d4; |
|
font-weight: 600; |
|
display: flex; |
|
align-items: center; |
|
gap: 15px; |
|
} |
|
@keyframes fadeIn { |
|
from { opacity: 0; transform: translateY(10px); } |
|
to { opacity: 1; transform: translateY(0); } |
|
} |
|
.stTextInput>div>input, .stTextArea textarea { |
|
background-color: rgba(26, 43, 30, 0.95) !important; |
|
border-radius: 10px !important; |
|
border: 1px solid #b8860b !important; |
|
padding: 12px !important; |
|
font-family: 'Shabnam', Tahoma; |
|
font-weight: 500; |
|
font-size: 16px; |
|
color: #d4d4d4 !important; |
|
} |
|
hr { |
|
border: 1px solid #b8860b; |
|
margin: 15px 0; |
|
} |
|
[data-testid="stSidebar"] > div { |
|
border: none !important; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
|
|
if "authenticated" not in st.session_state: |
|
st.session_state.authenticated = False |
|
|
|
if not st.session_state.authenticated: |
|
st.markdown('<style>.stTextInput > div[data-baseweb="input"] + div, .stTextInput div:has(div[role="alert"]) { display: none !important; }</style>', unsafe_allow_html=True) |
|
st.markdown(""" |
|
<style> |
|
input { |
|
background-color: #1e1e1e; |
|
color: gold; |
|
border: 1px solid gold; |
|
border-radius: 10px; |
|
padding: 10px; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
username = st.text_input("نام کاربری:", placeholder="شناسه نظامی خود را وارد کنید", |
|
label_visibility="visible") |
|
|
|
password = st.text_input("رمز عبور:", placeholder="رمز عبور نظامی", type="password", |
|
label_visibility="visible") |
|
|
|
if st.button("ورود"): |
|
if username == "admin" and password == "123": |
|
st.session_state.authenticated = True |
|
st.rerun() |
|
else: |
|
st.markdown(""" |
|
<div style="background-color: rgba(241, 196, 15, 0.6); color: #1a2b1e; padding: 10px; border-radius: 10px; border: 2px solid #b8860b; margin-top: 20px; text-align: center; backdrop-filter: blur(5px);"> |
|
نام کاربری یا رمز عبور اشتباه است. |
|
</div> |
|
""", 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://cdn-icons-png.flaticon.com/512/709/709496.png"), |
|
("تحلیل دادههای نظامی", "https://cdn-icons-png.flaticon.com/512/1828/1828932.png"), |
|
("مدیریت منابع", "https://cdn-icons-png.flaticon.com/512/681/681494.png"), |
|
("دستیار فرماندهی", "https://cdn-icons-png.flaticon.com/512/3601/3601646.png"), |
|
("تنظیمات امنیتی", "https://cdn-icons-png.flaticon.com/512/2099/2099058.png"), |
|
("پشتیبانی فنی", "https://cdn-icons-png.flaticon.com/512/597/597177.png"), |
|
] |
|
for idx, (text, icon) in enumerate(menu_items): |
|
st.markdown(f""" |
|
<div class="menu-item"> |
|
<img src="{icon}" /> |
|
{text} |
|
</div> |
|
""", unsafe_allow_html=True) |
|
if idx in [1, 3, 5]: |
|
st.markdown("<hr/>", unsafe_allow_html=True) |
|
|
|
st.markdown(""" |
|
<style> |
|
@font-face { |
|
font-family: 'IRANSans'; |
|
src: url('https://cdn.jsdelivr.net/gh/rastikerdar/iransans/font/IRANSans.woff2') format('woff2'), |
|
url('https://cdn.jsdelivr.net/gh/rastikerdar/iransans/font/IRANSans.woff') format('woff'); |
|
font-weight: 400; |
|
font-style: normal; |
|
} |
|
|
|
.header-text h1 { |
|
font-family: 'IRANSans', Tahoma, sans-serif !important; |
|
font-weight: 900 !important; |
|
font-size: 50px !important; |
|
color: #b8860b !important; |
|
margin: 0 !important; |
|
} |
|
|
|
.header-text .subtitle { |
|
font-family: 'IRANSans', Tahoma, sans-serif !important; |
|
font-weight: 600 !important; |
|
font-size: 24px !important; |
|
color: #d4d4d4 !important; |
|
margin-top: 10px !important; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
st.markdown(""" |
|
<div class="header-text"> |
|
<h1>رزمیار ارتش</h1> |
|
<div class="subtitle">دستیار هوشمند ارتش جمهوری اسلامی ایران</div> |
|
</div> |
|
""", 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" |
|
) |
|
|
|
|
|
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) |
|
file_text = "\n".join([para.text for para in doc.paragraphs]) |
|
if file_text.strip(): |
|
normalized = normalizer.normalize(file_text) |
|
return sentence_tokenizer.tokenize(normalized) |
|
except: |
|
return [] |
|
return [] |
|
|
|
all_sentences = [] |
|
with concurrent.futures.ThreadPoolExecutor() as executor: |
|
results = executor.map(process_docx, [f for f in os.listdir(path) if f.endswith(".docx")]) |
|
for sentences in results: |
|
if sentences: |
|
all_sentences.extend(sentences) |
|
return all_sentences |
|
|
|
all_sentences = load_and_process_documents(folder_path) |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
/* استایل برای کلاس خاص st-emotion-cache-128upt6 eht7o1d3 */ |
|
.st-emotion-cache-128upt6.eht7o1d3 { |
|
background-color: rgba(68, 83, 63, 0.8) !important; /* سبز تیره (44533f) */ |
|
border-radius: 10px !important; /* گوشههای گرد */ |
|
color: #d4d4d4 !important; /* رنگ متن روشن */ |
|
font-family: 'Vazirmatn', Tahoma, sans-serif !important; |
|
padding: 15px !important; /* فضای داخلی بیشتر */ |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important; /* سایه برای برجسته شدن */ |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
st.markdown(""" |
|
<style> |
|
/* استایل برای کلاس خاص */ |
|
.st-ae.st-bd.st-be.st-bf.st-bg.st-bh.st-bi.st-bj.st-bk.st-bl.st-bm.st-ah.st-bn.st-bo.st-bp.st-bq.st-br.st-bs.st-ci.st-cj.st-ax.st-ay.st-az.st-bv.st-b1.st-b2.st-bc.st-bw.st-bx.st-by.st-ck.st-cl.st-cn { |
|
background-color: rgba(106, 127, 83, 0.8) !important; /* سبز خاکی مایل به زرد (#6a7f53) */ |
|
border-radius: 10px !important; /* گوشههای گرد */ |
|
color: #d4d4d4 !important; /* رنگ متن روشن */ |
|
font-family: 'Vazirmatn', Tahoma, sans-serif !important; |
|
padding: 15px !important; /* فضای داخلی بیشتر */ |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important; /* سایه برای برجسته شدن */ |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
st.markdown(""" |
|
<style> |
|
/* استایل برای کلاس st-emotion-cache-yd4u6l e1togvvn1 */ |
|
.st-emotion-cache-yd4u6l.e1togvvn1 { |
|
background-color: rgba(106, 127, 83, 0.8) !important; /* سبز خاکی مایل به زرد (#6a7f53) */ |
|
border-radius: 10px !important; /* گوشههای گرد */ |
|
color: #d4d4d4 !important; /* رنگ متن روشن */ |
|
font-family: 'Vazirmatn', Tahoma, sans-serif !important; |
|
padding: 15px !important; /* فضای داخلی بیشتر */ |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important; /* سایه برای برجسته شدن */ |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
st.markdown(""" |
|
<style> |
|
/* استایل برای هدر */ |
|
.stAppHeader.st-emotion-cache-12fmjuu.e4hpqof0 { |
|
background-color: rgba(42, 55, 39, 0.9) !important; /* سبز تیرهتر */ |
|
color: #d4d4d4 !important; /* رنگ متن روشن */ |
|
font-family: 'Vazirmatn', Tahoma, sans-serif !important; |
|
padding: 20px !important; /* فضای داخلی بیشتر */ |
|
border-radius: 10px !important; /* گوشههای گرد */ |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important; /* سایه برای برجسته شدن */ |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
query = st.chat_input("چطور میتونم کمک کنم؟") |
|
if query: |
|
found = False |
|
threshold = 60 |
|
|
|
for idx, sentence in enumerate(all_sentences): |
|
similarity = fuzz.partial_ratio(query, sentence) |
|
if similarity >= threshold: |
|
next_sentences = [] |
|
for i in range(1, 10): |
|
if idx + i < len(all_sentences): |
|
next_sentences.append(all_sentences[idx + i]) |
|
|
|
total_text = sentence + " " + " ".join(next_sentences) |
|
prompt = f""" |
|
تعدادی پاسخ برای سوال زیر تولید شده است. لطفاً ابتدا این پاسخها را بررسی کن، سپس با در نظر گرفتن محتوای سوال و لحن آن، یک پاسخ نهایی حرفهای، دقیق و روان ارائه کن که هم به سوال پاسخ دهد و هم از نظر نگارشی و ساختاری در سطح بالایی باشد. از تکرار اضافی پرهیز کن و محتوای چند پاسخ را در صورت نیاز با هم ترکیب کن تا بهترین نتیجه حاصل شود. |
|
|
|
سوال: |
|
{query} |
|
|
|
پاسخها: |
|
{total_text} |
|
|
|
پاسخ نهایی حرفهای بازنویسیشده: |
|
""" |
|
|
|
SystemMessage(content="You are a helpful assistant."), |
|
HumanMessage(content=prompt) |
|
]) |
|
rewritten = response.content.strip() |
|
st.markdown(f'<div class="chat-message">{rewritten}</div>', unsafe_allow_html=True) |
|
found = True |
|
break |
|
|
|
if not found: |
|
prompt = f"لطفاً بر اساس سوال زیر یک متن مرتبط و معنادار تولید کن:\n\nسوال: {query}" |
|
response = llm([ |
|
SystemMessage(content="You are a helpful assistant."), |
|
HumanMessage(content=prompt) |
|
]) |
|
rewritten = response.content.strip() |
|
st.markdown(f'<div class="chat-message">{rewritten}</div>', unsafe_allow_html=True) |