M17idd commited on
Commit
5264200
·
verified ·
1 Parent(s): de4be5c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -342
app.py CHANGED
@@ -1,346 +1,84 @@
1
- import time
2
- import streamlit as st
3
- from langchain.document_loaders import PyPDFLoader
4
- from langchain.text_splitter import RecursiveCharacterTextSplitter
5
- from langchain.embeddings.base import Embeddings
6
- from langchain.vectorstores import FAISS
7
- from langchain.indexes import VectorstoreIndexCreator
8
- from langchain.chains import RetrievalQA
9
- from langchain.chat_models import ChatOpenAI
10
- from typing import List
11
- from together import Together
12
- import pandas as pd
13
- import streamlit as st
14
- from langchain.docstore.document import Document
15
- import docx
16
  import os
17
-
 
 
 
18
  from hazm import *
 
19
 
20
-
21
-
22
-
23
-
24
- st.markdown("""
25
- <style>
26
- @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap');
27
-
28
- html, body, [class*="css"] {
29
- font-family: 'Vazirmatn', Tahoma, sans-serif;
30
- direction: rtl;
31
- text-align: right;
32
- }
33
-
34
- .stApp {
35
- background: linear-gradient(to left, #4b5e40, #2e3b2e);
36
- color: #ffffff;
37
- }
38
-
39
- /* استایل سایدبار */
40
- [data-testid="stSidebar"] {
41
- width: 260px !important;
42
- background-color: #1a2b1e;
43
- border: none !important; /* حذف حاشیه زرد */
44
- padding-top: 20px;
45
- }
46
-
47
- .menu-item {
48
- display: flex;
49
- align-items: center;
50
- gap: 12px;
51
- padding: 12px 20px;
52
- font-size: 16px;
53
- color: #d4d4d4;
54
- cursor: pointer;
55
- transition: background-color 0.3s ease;
56
- }
57
-
58
- .menu-item:hover {
59
- background-color: #2e3b2e;
60
- color: #b8860b;
61
- }
62
-
63
- .menu-item img {
64
- width: 24px;
65
- height: 24px;
66
- }
67
-
68
- /* استایل دکمه‌ها */
69
- .stButton>button {
70
- background-color: #b8860b !important;
71
- color: #1a2b1e !important;
72
- font-family: 'Vazirmatn', Tahoma;
73
- font-weight: 700;
74
- border-radius: 10px;
75
- padding: 12px 24px;
76
- border: none;
77
- transition: all 0.3s ease;
78
- font-size: 16px;
79
- width: 100%;
80
- margin: 10px 0;
81
- }
82
-
83
- .stButton>button:hover {
84
- background-color: #8b6508 !important;
85
- transform: translateY(-2px);
86
- box-shadow: 0 4px 8px rgba(0,0,0,0.3);
87
- }
88
-
89
- /* استایل هدر */
90
- .header-text {
91
- text-align: center;
92
- margin: 20px 0;
93
- background-color: rgba(26, 43, 30, 0.9);
94
- padding: 25px;
95
- border-radius: 15px;
96
- box-shadow: 0 6px 12px rgba(0,0,0,0.4);
97
- }
98
-
99
- .header-text h1 {
100
- font-size: 42px;
101
- color: #b8860b;
102
- margin: 0;
103
- font-weight: 700;
104
- }
105
-
106
- .subtitle {
107
- font-size: 18px;
108
- color: #d4d4d4;
109
- margin-top: 10px;
110
- }
111
-
112
- /* استایل پیام چت */
113
- .chat-message {
114
- background-color: rgba(26, 43, 30, 0.95);
115
- border: 2px solid #b8860b;
116
- border-radius: 15px;
117
- padding: 20px;
118
- margin: 15px 0;
119
- box-shadow: 0 6px 12px rgba(0,0,0,0.3);
120
- animation: fadeIn 0.6s ease;
121
- font-size: 18px;
122
- color: #d4d4d4;
123
- display: flex;
124
- align-items: center;
125
- gap: 15px;
126
- }
127
-
128
- @keyframes fadeIn {
129
- from { opacity: 0; transform: translateY(10px); }
130
- to { opacity: 1; transform: translateY(0); }
131
- }
132
-
133
- /* استایل ورودی‌ها */
134
- .stTextInput>div>input, .stTextArea textarea {
135
- background-color: rgba(26, 43, 30, 0.95) !important;
136
- border-radius: 10px !important;
137
- border: 1px solid #b8860b !important;
138
- padding: 12px !important;
139
- font-family: 'Vazirmatn', Tahoma;
140
- font-size: 16px;
141
- color: #d4d4d4 !important;
142
- }
143
-
144
- img.small-logo {
145
- width: 120px;
146
- margin: 0 auto 20px;
147
- display: block;
148
- }
149
-
150
- hr {
151
- border: 1px solid #b8860b;
152
- margin: 15px 0;
153
- }
154
-
155
- /* رفع مشکل نوار زرد */
156
- [data-testid="stSidebar"] > div {
157
- border: none !important;
158
- }
159
- </style>
160
- """, unsafe_allow_html=True)
161
-
162
- # ----------------- احراز هویت ساده -----------------
163
- if "authenticated" not in st.session_state:
164
- st.session_state.authenticated = False
165
-
166
- if not st.session_state.authenticated:
167
- st.markdown("<h3 style='text-align: center; color: #b8860b;'>ورود به رزم‌یار ارتش</h3>", unsafe_allow_html=True)
168
- username = st.text_input("نام کاربری:", placeholder="شناسه نظامی خود را وارد کنید")
169
- password = st.text_input("رمز عبور:", type="password", placeholder="رمز عبور نظامی")
170
- if st.button("ورود"):
171
- if username == "admin" and password == "123":
172
- st.session_state.authenticated = True
173
- st.rerun()
174
- else:
175
- st.error("نام کاربری یا رمز عبور اش��باه است.")
176
- st.stop()
177
-
178
- # ----------------- سایدبار -----------------
179
- with st.sidebar:
180
- st.image("log.png", use_container_width=True) # اصلاح use_column_width
181
-
182
- menu_items = [
183
- ("گزارش عملیاتی", "https://cdn-icons-png.flaticon.com/512/3596/3596165.png"),
184
- ("تاریخچه ماموریت‌ها", "https://cdn-icons-png.flaticon.com/512/709/709496.png"),
185
- ("تحلیل داده‌های نظامی", "https://cdn-icons-png.flaticon.com/512/1828/1828932.png"),
186
- ("مدیریت منابع", "https://cdn-icons-png.flaticon.com/512/681/681494.png"),
187
- ("دستیار فرماندهی", "https://cdn-icons-png.flaticon.com/512/3601/3601646.png"),
188
- ("تنظیمات امنیتی", "https://cdn-icons-png.flaticon.com/512/2099/2099058.png"),
189
- ("پشتیبانی فنی", "https://cdn-icons-png.flaticon.com/512/597/597177.png"),
190
- ]
191
-
192
- for idx, (text, icon) in enumerate(menu_items):
193
- st.markdown(f"""
194
- <div class="menu-item">
195
- <img src="{icon}" />
196
- {text}
197
- </div>
198
- """, unsafe_allow_html=True)
199
- if idx in [1, 3, 5]:
200
- st.markdown("<hr/>", unsafe_allow_html=True)
201
-
202
- # ----------------- محتوای اصلی -----------------
203
- st.markdown("""
204
- <div class="header-text">
205
- <h1>رزم‌یار ارتش</h1>
206
- <div class="subtitle">دستیار هوشمندارتش</div>
207
- </div>
208
- """, unsafe_allow_html=True)
209
-
210
- # پیام خوش‌آمدگویی
211
- st.markdown(f"""
212
- <div class="chat-message">
213
- <span style="font-size: 24px;">🪖</span>
214
- <span>به رزم‌ یار ارتش خوش آمدید. </span>
215
- </div>
216
- """, unsafe_allow_html=True)
217
-
218
-
219
- # ----------------- لود csv و ساخت ایندکس -----------------
220
- normalizer = Normalizer()
221
-
222
- # توکنایزر هضم
223
- tokenizer = word_tokenize
224
-
225
- # بارگذاری مدل WordEmbedding
226
- word_embedding = WordEmbedding(model_type='fasttext')
227
- WordEmbedding = word_embedding.load_model('word2vec.bin') # مدل از اینترنت دانلود می‌شود
228
-
229
- class CustomEmbeddings(Embeddings):
230
- def __init__(self, word_embedding: WordEmbedding):
231
- self.word_embedding = word_embedding
232
-
233
- def embed_documents(self, texts: List[str]) -> List[List[float]]:
234
- embeddings = []
235
- for text in texts:
236
- # ایجاد امبدینگ برای هر کلمه در متن
237
- embeddings.append([self.word_embedding.embed(word) for word in tokenizer(text)])
238
- return embeddings
239
-
240
- def embed_query(self, text: str) -> List[float]:
241
- return self.embed_documents([text])[0]
242
-
243
  @st.cache_resource
244
- def get_docx_index(folder_path):
245
- with st.spinner('📄 در حال پردازش فایل‌های Word...'):
246
- texts = []
247
-
248
- # خواندن تمام فایل‌های .docx در پوشه
249
- for filename in os.listdir(folder_path):
250
- if filename.endswith(".docx"):
251
- full_path = os.path.join(folder_path, filename)
252
- doc = docx.Document(full_path)
253
-
254
- # استخراج متن تمام پاراگراف‌ها
255
- file_text = "\n".join([para.text for para in doc.paragraphs])
256
- if file_text.strip():
257
- texts.append(file_text)
258
-
259
- # نرمال‌سازی و توکنایز کردن متن‌ها
260
- normalized_texts = [normalizer.normalize(text) for text in texts]
261
- tokenized_texts = [tokenizer(text) for text in normalized_texts]
262
-
263
- # تقسیم متن‌ها
264
- text_splitter = RecursiveCharacterTextSplitter(
265
- chunk_size=300,
266
- chunk_overlap=50,
267
- length_function=len,
268
- separators=["\n\n", "\n", " ", ""]
269
- )
270
- split_texts = []
271
- for text in normalized_texts:
272
- split_texts.extend(text_splitter.split_text(text))
273
-
274
- # ایجاد embedding با استفاده از WordEmbedding
275
- embeddings = CustomEmbeddings(word_embedding=word_embedding)
276
-
277
- # ساخت ایندکس
278
- index_creator = VectorstoreIndexCreator(
279
- embedding=embeddings,
280
- text_splitter=text_splitter
281
- )
282
-
283
- documents = [Document(page_content=text) for text in split_texts]
284
-
285
- return index_creator.from_documents(documents)
286
-
287
- # مسیر فایل CSV
288
- folder_path = '46/'
289
-
290
- try:
291
- docx_index = get_docx_index(folder_path)
292
- except Exception as e:
293
- st.error(f" خطا در ساخت ایندکس: {e}")
294
-
295
- #------------------------------------------
296
- llm = ChatOpenAI(
297
- base_url="https://api.together.xyz/v1",
298
- api_key='0291f33aee03412a47fa5d8e562e515182dcc5d9aac5a7fb5eefdd1759005979',
299
- model="meta-llama/Llama-3.3-70B-Instruct-Turbo-Free"
300
- )
301
-
302
- chain = RetrievalQA.from_chain_type(
303
- llm=llm,
304
- chain_type='stuff',
305
- retriever=docx_index.vectorstore.as_retriever(),
306
- input_key='question'
307
- )
308
-
309
- if 'messages' not in st.session_state:
310
- st.session_state.messages = []
311
-
312
- if 'pending_prompt' not in st.session_state:
313
- st.session_state.pending_prompt = None
314
-
315
- for msg in st.session_state.messages:
316
- with st.chat_message(msg['role']):
317
- st.markdown(f"🗨️ {msg['content']}", unsafe_allow_html=True)
318
-
319
- prompt = st.chat_input("چطور می‌تونم کمک کنم؟")
320
-
321
- if prompt:
322
- st.session_state.messages.append({'role': 'user', 'content': prompt})
323
- st.session_state.pending_prompt = prompt
324
- st.rerun()
325
-
326
- if st.session_state.pending_prompt:
327
- with st.chat_message('ai'):
328
- thinking = st.empty()
329
- thinking.markdown("🤖 در حال فکر کردن...")
330
-
331
- response = chain.run(f'پاسخ را فقط به زبان فارسی جواب بده به هیچ عنوان از زبان چینی در پاسخ استفاده نکن. سوال: {st.session_state.pending_prompt}')
332
- answer = response.split("Helpful Answer:")[-1].strip() if "Helpful Answer:" in response else response.strip()
333
- if not answer:
334
- answer = "متأسفم، اطلاعات دقیقی در این مورد ندارم."
335
-
336
- thinking.empty()
337
- full_response = ""
338
- placeholder = st.empty()
339
- for word in answer.split():
340
- full_response += word + " "
341
- placeholder.markdown(full_response + "▌")
342
- time.sleep(0.03)
343
-
344
- placeholder.markdown(full_response)
345
- st.session_state.messages.append({'role': 'ai', 'content': full_response})
346
- st.session_state.pending_prompt = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import docx
3
+ import torch
4
+ import numpy as np
5
+ import streamlit as st
6
  from hazm import *
7
+ from transformers import AutoTokenizer, AutoModel
8
 
9
+ # بارگذاری مدل
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  @st.cache_resource
11
+ def load_model():
12
+ tokenizer = AutoTokenizer.from_pretrained("HooshvareLab/bert-fa-base-uncased")
13
+ model = AutoModel.from_pretrained("HooshvareLab/bert-fa-base-uncased")
14
+ return tokenizer, model
15
+
16
+ tokenizer, model = load_model()
17
+
18
+ # پردازش فایل‌های Word و تبدیل به جملات
19
+ @st.cache_data
20
+ def load_text_chunks(folder_path):
21
+ normalizer = Normalizer()
22
+ sentence_tokenizer = SentenceTokenizer()
23
+ texts = []
24
+
25
+ for filename in os.listdir(folder_path):
26
+ if filename.endswith(".docx"):
27
+ full_path = os.path.join(folder_path, filename)
28
+ doc = docx.Document(full_path)
29
+ file_text = "\n".join([para.text for para in doc.paragraphs])
30
+ if file_text.strip():
31
+ texts.append(file_text)
32
+
33
+ all_sentences = []
34
+ for text in texts:
35
+ normalized = normalizer.normalize(text)
36
+ sentences = sentence_tokenizer.tokenize(normalized)
37
+ all_sentences.extend(sentences)
38
+
39
+ # تقسیم به بخش‌های ۵ جمله‌ای
40
+ chunks = []
41
+ for i in range(0, len(all_sentences), 5):
42
+ chunk = " ".join(all_sentences[i:i+5])
43
+ if chunk:
44
+ chunks.append(chunk)
45
+ return chunks
46
+
47
+ # محاسبه embedding با BERT
48
+ def get_embedding(text):
49
+ inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
50
+ with torch.no_grad():
51
+ outputs = model(**inputs)
52
+ embeddings = outputs.last_hidden_state.mean(dim=1)
53
+ return embeddings.squeeze().numpy()
54
+
55
+ # شباهت کسینوسی
56
+ def cosine_similarity(vec1, vec2):
57
+ return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
58
+
59
+ # رابط کاربری استریم‌لیت
60
+ st.title("🔎 یافتن نزدیک‌ترین بخش ۵ جمله‌ای به ورودی شما")
61
+ st.markdown("با استفاده از مدل `HooshvareLab/bert-fa-base-uncased`")
62
+
63
+ # مسیر پوشه فایل‌های docx
64
+ folder_path = 'C:/Users/ici/Downloads/Telegram Desktop/45/46'
65
+
66
+ # بارگذاری و نمایش تعداد بخش‌ها
67
+ chunks = load_text_chunks(folder_path)
68
+ st.success(f"{len(chunks)} بخش ۵ جمله‌ای بارگذاری شد.")
69
+
70
+ # ورودی کاربر
71
+ user_input = st.text_area("لطفاً جمله یا متن خود را وارد کنید:")
72
+
73
+ if st.button("🔍 جستجو"):
74
+ if not user_input.strip():
75
+ st.warning("لطفاً یک جمله وارد کنید.")
76
+ else:
77
+ with st.spinner("در حال محاسبه شباهت‌ها..."):
78
+ user_embedding = get_embedding(user_input)
79
+ similarities = [cosine_similarity(user_embedding, get_embedding(chunk)) for chunk in chunks]
80
+ most_similar_index = np.argmax(similarities)
81
+ result = chunks[most_similar_index]
82
+
83
+ st.subheader("📌 شبیه‌ترین بخش ۵ جمله‌ای:")
84
+ st.write(result)