""", 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 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)
# تابعی برای پیدا کردن نزدیکترین خطوط به سوال
def find_closest_lines(query, doc_texts, top_n=20, exclude_line=None):
# تقسیم سوال به کلمات
query_words = 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]]
# حذف خط خاص از لیست در صورت وجود
if exclude_line and exclude_line in closest_lines:
closest_lines.remove(exclude_line)
return closest_lines
# حالا این رو در کد اصلی استفاده میکنیم:
if query:
# پیدا کردن ۲۰ خط نزدیکتر به سوال (و حذف یک خط خاص)
closest_lines = find_closest_lines(query, doc_texts, top_n=20, exclude_line=None)
if closest_lines:
prompt = f"""
لطفاً با توجه به سؤال زیر و محتوای خطوط مرتبط، یک پاسخ نهایی حرفهای، دقیق و روان تولید کن. فقط از متن خطوط مرتبط استفاده کن. اگر اطلاعات کافی در متن وجود ندارد، صادقانه اعلام کن.
سوال:
{query}
خطوط مرتبط:
{closest_lines}
پاسخ نهایی:
"""
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)
else:
st.warning("هیچ خط مرتبطی پیدا نشد.")