|
import time |
|
import streamlit as st |
|
from langchain.document_loaders import PyPDFLoader |
|
from langchain.text_splitter import RecursiveCharacterTextSplitter |
|
from langchain.embeddings.base import Embeddings |
|
from langchain.vectorstores import FAISS |
|
from langchain.indexes import VectorstoreIndexCreator |
|
from langchain.chains import RetrievalQA |
|
from langchain.chat_models import ChatOpenAI |
|
from typing import List |
|
from together import Together |
|
import pandas as pd |
|
import streamlit as st |
|
from sklearn.metrics.pairwise import cosine_similarity |
|
|
|
|
|
import numpy as np |
|
from sentence_transformers import SentenceTransformer |
|
import faiss |
|
|
|
|
|
|
|
st.set_page_config(page_title="رزم یار ارتش", page_icon="🪖", layout="wide") |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap'); |
|
html, body, [class*="css"] { |
|
font-family: 'Vazirmatn', Tahoma, sans-serif; |
|
direction: rtl; |
|
text-align: right; |
|
} |
|
.stApp { |
|
background: linear-gradient(to left, #f0f4f7, #d9e2ec); |
|
} |
|
.sidebar .sidebar-content { |
|
background-color: #ffffff; |
|
border-left: 2px solid #4e8a3e; |
|
padding-top: 10px; |
|
} |
|
.sidebar .sidebar-content div { |
|
margin-bottom: 10px; |
|
font-weight: bold; |
|
color: #2c3e50; |
|
font-size: 15px; |
|
} |
|
.stButton>button { |
|
background-color: #4e8a3e !important; |
|
color: white !important; |
|
font-weight: bold; |
|
border-radius: 8px; |
|
padding: 5px 16px; |
|
transition: 0.3s; |
|
font-size: 14px; |
|
} |
|
.stButton>button:hover { |
|
background-color: #3c6d30 !important; |
|
} |
|
.header-text { |
|
text-align: center; |
|
margin-top: 15px; |
|
margin-bottom: 25px; |
|
background-color: rgba(255, 255, 255, 0.85); |
|
padding: 16px; |
|
border-radius: 16px; |
|
box-shadow: 0 4px 10px rgba(0,0,0,0.1); |
|
} |
|
.header-text h1 { |
|
font-size: 36px; |
|
color: #2c3e50; |
|
margin: 0; |
|
font-weight: bold; |
|
} |
|
.subtitle { |
|
font-size: 16px; |
|
color: #34495e; |
|
margin-top: 5px; |
|
} |
|
.chat-message { |
|
background-color: rgba(255, 255, 255, 0.95); |
|
border: 1px solid #4e8a3e; |
|
border-radius: 12px; |
|
padding: 14px; |
|
margin-bottom: 10px; |
|
box-shadow: 0 4px 8px rgba(0,0,0,0.08); |
|
animation: fadeIn 0.5s ease; |
|
} |
|
.stTextInput>div>input, .stTextArea textarea { |
|
background-color: rgba(255,255,255,0.9) !important; |
|
border-radius: 8px !important; |
|
direction: rtl; |
|
text-align: right; |
|
font-family: 'Vazirmatn', Tahoma; |
|
} |
|
img.small-logo { |
|
width: 90px; |
|
margin-bottom: 15px; |
|
display: block; |
|
margin-right: auto; |
|
margin-left: auto; |
|
} |
|
.menu-item { |
|
display: flex; |
|
align-items: center; |
|
gap: 8px; |
|
padding: 6px 0; |
|
font-size: 15px; |
|
cursor: pointer; |
|
} |
|
.menu-item img { |
|
width: 20px; |
|
height: 20px; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
with st.sidebar: |
|
st.image("log.png", width=90) |
|
|
|
|
|
st.markdown(""" |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/3596/3596165.png" /> |
|
گفتگوی جدید |
|
</div> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/709/709496.png" /> |
|
تاریخچه |
|
</div> |
|
<hr/> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/1828/1828932.png" /> |
|
مدلهای هوش مصنوعی |
|
</div> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/681/681494.png" /> |
|
تولید محتوا |
|
</div> |
|
<hr/> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/3601/3601646.png" /> |
|
دستیار ویژه |
|
</div> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/709/709612.png" /> |
|
ابزار مالی |
|
</div> |
|
<hr/> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/2099/2099058.png" /> |
|
تنظیمات |
|
</div> |
|
<div class="menu-item"> |
|
<img src="https://cdn-icons-png.flaticon.com/512/597/597177.png" /> |
|
پشتیبانی |
|
</div> |
|
""", unsafe_allow_html=True) |
|
st.markdown(""" |
|
<style> |
|
/* تنظیم سایز سایدبار */ |
|
[data-testid="stSidebar"] { |
|
width: 220px !important; |
|
flex-shrink: 0; |
|
} |
|
[data-testid="stSidebar"] > div { |
|
width: 220px !important; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
st.markdown(""" |
|
<div class="header-text"> |
|
<h1>رزم یار ارتش</h1> |
|
<div class="subtitle">دستیار هوشمند ارتشی برای پشتیبانی و راهبری</div> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
st.markdown('<div class="chat-message">👋 سلام! چطور میتونم کمکتون کنم؟</div>', unsafe_allow_html=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@st.cache_resource |
|
def get_embedding_model(): |
|
return SentenceTransformer("HooshvareLab/bert-fa-zwnj-base") |
|
|
|
@st.cache_resource |
|
def process_csv(csv_file): |
|
df = pd.read_csv(csv_file) |
|
texts = df.iloc[:, 0].astype(str).tolist() |
|
texts = [text for text in texts if text.strip()] |
|
|
|
text_splitter = RecursiveCharacterTextSplitter( |
|
chunk_size=200, |
|
chunk_overlap=50, |
|
length_function=len, |
|
separators=["\n\n", "\n", " ", ""] |
|
) |
|
|
|
split_texts = [] |
|
for text in texts: |
|
split_texts.extend(text_splitter.split_text(text)) |
|
|
|
|
|
model = get_embedding_model() |
|
embeddings = model.encode(split_texts, show_progress_bar=True) |
|
|
|
dim = embeddings.shape[1] |
|
index = faiss.IndexHNSWFlat(dim, 32) |
|
index.hnsw.efSearch = 50 |
|
index.add(np.array(embeddings)) |
|
|
|
return split_texts, embeddings, index |
|
|
|
|
|
csv_file_path = 'output (1).csv' |
|
|
|
texts, vectors, index = process_csv(csv_file_path) |
|
|
|
|
|
if 'messages' not in st.session_state: |
|
st.session_state.messages = [] |
|
|
|
if 'pending_prompt' not in st.session_state: |
|
st.session_state.pending_prompt = None |
|
|
|
for msg in st.session_state.messages: |
|
with st.chat_message(msg['role']): |
|
st.markdown(msg['content'], unsafe_allow_html=True) |
|
|
|
query = st.chat_input("سؤالت را بپرس...") |
|
|
|
if query: |
|
st.session_state.messages.append({'role': 'user', 'content': query}) |
|
st.session_state.pending_prompt = query |
|
st.rerun() |
|
|
|
if st.session_state.pending_prompt: |
|
with st.chat_message("ai"): |
|
thinking = st.empty() |
|
thinking.markdown("🤖 در حال جستجو...") |
|
|
|
model = get_embedding_model() |
|
query_vector = model.encode([st.session_state.pending_prompt]) |
|
|
|
D, I = index.search(np.array(query_vector), k=10) |
|
|
|
top_indices = I[0] |
|
top_texts = [texts[i] for i in top_indices] |
|
top_vectors = np.array([vectors[i] for i in top_indices]) |
|
|
|
|
|
similarities = cosine_similarity(query_vector, top_vectors)[0] |
|
|
|
|
|
best_match_relative_index = np.argmax(similarities) |
|
best_match_index = top_indices[best_match_relative_index] |
|
best_match_text = texts[best_match_index] |
|
response = "🧠 پاسخ سوال :\n\n" .join(best_match_text) |
|
|
|
thinking.empty() |
|
full_response = "" |
|
placeholder = st.empty() |
|
for word in response.split(): |
|
full_response += word + " " |
|
placeholder.markdown(full_response + "▌") |
|
time.sleep(0.02) |
|
|
|
placeholder.markdown(full_response) |
|
st.session_state.messages.append({'role': 'ai', 'content': full_response}) |
|
st.session_state.pending_prompt = None |
|
|