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
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)
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)
with open('stopwords.txt', 'r', encoding='utf-8') as file:
stop_words = set(file.read().splitlines())
def remove_stop_words(text, stop_words):
words = text.split()
return " ".join([word for word in words if word not in stop_words])
def extract_keywords_from_text(text, query_words):
matched_lines = []
lines = text.split("\n")
for line in lines:
if any(query_word in line for query_word in query_words):
matched_lines.append(line)
return matched_lines
def clean_text(text):
return re.sub(r'[^آ-ی۰-۹0-9،.؟!؛+\-* ]+', '', text)
from collections import Counter
import heapq
def summarize_text_by_frequency(text, num_sentences=1):
sentences = text.split('\n')
word_freq = Counter()
for sentence in sentences:
for word in sentence.split():
if word not in stop_words:
word_freq[word] += 1
sentence_scores = {}
for sentence in sentences:
for word in sentence.split():
if word in word_freq:
sentence_scores[sentence] = sentence_scores.get(sentence, 0) + word_freq[word]
summarized_sentences = heapq.nlargest(num_sentences, sentence_scores, key=sentence_scores.get)
return "\n".join(summarized_sentences)
def find_closest_lines(query, doc_texts, stop_words, top_n=5):
cleaned_query = remove_stop_words(query, stop_words)
query_words = cleaned_query.split()
all_matched_lines = []
for filename, text in doc_texts.items():
matched_lines = extract_keywords_from_text(text, query_words)
for line in matched_lines:
similarity = fuzz.partial_ratio(query, line)
all_matched_lines.append((line, similarity))
all_matched_lines.sort(key=lambda x: x[1], reverse=True)
closest_lines = [line for line, _ in all_matched_lines[:top_n]]
return closest_lines
def remove_stop_words_from_lines(lines, stop_words):
cleaned_lines = []
for line in lines:
words = line.split()
cleaned_words = [word for word in words if word not in stop_words]
cleaned_lines.append(" ".join(cleaned_words))
return cleaned_lines
if query:
closest_lines = find_closest_lines(query, doc_texts, stop_words, top_n=5)
cleaned_closest_lines = [
clean_text(" ".join([word for word in line.split() if word not in stop_words]))
for line in closest_lines
]
summarized_text = summarize_text_by_frequency("\n".join(cleaned_closest_lines), num_sentences=1)
if summarized_text:
prompt = f"""
تعدادی جمله مرتبط با سوال زیر استخراج شده است. لطفاً ابتدا این جملات را بررسی کن، سپس با در نظر گرفتن محتوای سوال و لحن آن، یک پاسخ نهایی حرفهای، دقیق و روان ارائه کن که هم به سوال پاسخ دهد و هم از نظر نگارشی و ساختاری در سطح بالایی باشد. پاسخ نهایی باید حداکثر 1024 کاراکتر و حداقل 512 کاراکتر باشد، خلاصه و واضح نوشته شود و فقط به زبان فارسی باشد. از تکرار اضافی پرهیز کن و در صورت نیاز، محتوای جملات را ترکیب کن.
سوال:
{query}
جملات مرتبط:
{summarized_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)
think.empty()
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'