Reza-galaxy21 commited on
Commit
1f4020e
·
verified ·
1 Parent(s): e3cf94c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -0
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import logging
4
+ import gradio as gr
5
+ from langchain_community.document_loaders import PyPDFLoader
6
+ from langchain_community.embeddings import OpenAIEmbeddings
7
+ from langchain_community.vectorstores import FAISS
8
+ from langchain_community.chat_models import ChatOpenAI
9
+
10
+ # تنظیمات لاگ‌گیری
11
+ logging.basicConfig(level=logging.INFO)
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # تنظیمات مسیرها
15
+ UPLOAD_FOLDER = "uploaded_files"
16
+ DATABASE_FILE = "/home/user/app/vector_database"
17
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
18
+
19
+ # بررسی و بارگذاری دیتابیس برداری
20
+ def load_database():
21
+ try:
22
+ if os.path.exists(DATABASE_FILE):
23
+ embeddings = OpenAIEmbeddings(openai_api_key=os.getenv("My_huggingface_key"))
24
+ vector_db = FAISS.load_local(DATABASE_FILE, embeddings)
25
+ logger.info(f"✅ دیتابیس بارگذاری شد: {DATABASE_FILE}")
26
+ return vector_db
27
+ else:
28
+ logger.warning(f"❌ دیتابیس در مسیر `{DATABASE_FILE}` وجود ندارد.")
29
+ return None
30
+ except Exception as e:
31
+ logger.error(f"❌ خطا در بارگذاری دیتابیس: {e}")
32
+ return None
33
+
34
+ def save_database(vector_db):
35
+ try:
36
+ vector_db.save_local(DATABASE_FILE)
37
+ logger.info(f"✅ دیتابیس ذخیره شد: {DATABASE_FILE}")
38
+ except Exception as e:
39
+ logger.error(f"❌ خطا در ذخیره دیتابیس: {e}")
40
+ raise e
41
+
42
+ global_vector_db = load_database()
43
+
44
+ # پردازش و ذخیره‌سازی فایل‌های PDF
45
+ def process_and_store_pdfs(file_paths):
46
+ texts = []
47
+ for file_path in file_paths:
48
+ try:
49
+ logger.info(f"در حال پردازش فایل: {file_path}")
50
+ if file_path.endswith(".pdf"):
51
+ loader = PyPDFLoader(file_path)
52
+ documents = loader.load()
53
+ texts.extend(documents)
54
+ logger.info(f"✅ تعداد صفحات پردازش شده: {len(documents)}")
55
+ else:
56
+ logger.warning(f"فرمت فایل {file_path} پشتیبانی نمی‌شود.")
57
+ except Exception as e:
58
+ logger.error(f"خطا در پردازش فایل {file_path}: {e}")
59
+
60
+ try:
61
+ logger.info("در حال ایجاد embeddings و ذخیره‌سازی در FAISS...")
62
+ embeddings = OpenAIEmbeddings(openai_api_key=os.getenv("My_huggingface_key"))
63
+ vector_db = FAISS.from_documents(texts, embeddings)
64
+ logger.info(f"✅ ذخیره‌سازی در FAISS با موفقیت انجام شد. تعداد اسناد: {vector_db.index.ntotal}")
65
+ return vector_db
66
+ except Exception as e:
67
+ logger.error(f"خطا در ایجاد embeddings یا ذخیره‌سازی در FAISS: {e}")
68
+ return None
69
+
70
+ # ایجاد لینک منبع
71
+ def generate_source_link(source, page):
72
+ return f'<a href="{source}#page={page}" target="_blank">{source}, صفحه {page}</a>'
73
+
74
+ # پاسخ‌گویی بر اساس اسناد بارگذاری‌شده
75
+ def chat_with_doc(query):
76
+ try:
77
+ global global_vector_db
78
+ if not global_vector_db:
79
+ return "❌ لطفاً یک فایل مرتبط آپلود کنید."
80
+
81
+ if not query.strip():
82
+ return "❌ لطفاً سوال خود را وارد کنید."
83
+
84
+ retriever = global_vector_db.as_retriever(search_kwargs={"k": 8})
85
+ docs = retriever.get_relevant_documents(query)
86
+
87
+ if not docs:
88
+ return "هیچ اطلاعات مرتبطی یافت نشد."
89
+
90
+ # نمایش لاگ برای بررسی اسناد
91
+ for doc in docs:
92
+ logger.info(f"📄 سند: {doc.metadata.get('source', 'نامشخص')} | صفحه {doc.metadata.get('page', 'نامشخص')}")
93
+
94
+ # تفکیک بخش‌های نقل‌قول شده از متن سند
95
+ citations = []
96
+ context = ""
97
+ for doc in docs:
98
+ quoted_text = f"«{doc.page_content.strip()}»"
99
+ source_info = generate_source_link(doc.metadata.get("source", "نامشخص"), doc.metadata.get("page", "نامشخص"))
100
+ citations.append(f"{quoted_text} ({source_info})")
101
+ context += f"{quoted_text}\n\n"
102
+
103
+ llm = ChatOpenAI(model_name="gpt-3.5-turbo", openai_api_key=os.getenv("My_huggingface_key"))
104
+ prompt = f"""سوال: {query}\n\nاطلاعات مرتبط:\n{context}\n\nلطفاً به سوال پاسخ دهید:"""
105
+ response = llm.predict(prompt)
106
+
107
+ final_response = f"**پاسخ:**\n{response}\n\n**نقل‌قول‌های مستقیم:**\n" + "\n".join(citations)
108
+ return final_response
109
+ except Exception as e:
110
+ logger.error(f"خطا در پاسخ‌گویی بر اساس سند: {e}")
111
+ return f"❌ خطایی رخ داده است: {e}"
112
+
113
+ # فرمت کردن خروجی با HTML برای Gradio
114
+ def format_response(response_text):
115
+ response_text = response_text.replace("**پاسخ:**", "<h3 style='color:blue;'>پاسخ:</h3>")
116
+ response_text = response_text.replace("**نقل‌قول‌های مستقیم:**", "<h4 style='color:green;'>نقل‌قول‌های مستقیم:</h4>")
117
+ return response_text
118
+
119
+ # ذخیره فایل آپلود شده
120
+ def save_uploaded_file(file):
121
+ try:
122
+ file_name = os.path.basename(file)
123
+ file_path = os.path.join(UPLOAD_FOLDER, file_name)
124
+ shutil.copy(file, file_path)
125
+
126
+ global global_vector_db
127
+ global_vector_db = process_and_store_pdfs([file_path])
128
+ if global_vector_db:
129
+ save_database(global_vector_db)
130
+
131
+ return f"✅ فایل ذخیره شد: {file_path}"
132
+ except Exception as e:
133
+ return f"❌ خطا در ذخیره فایل: {e}"
134
+
135
+ # رابط کاربری با Gradio
136
+ with gr.Blocks() as demo:
137
+ gr.Markdown("# هوش مصنوعی همراه کارشناسان توزیع برق ایران")
138
+
139
+ query = gr.Textbox(label="سوال خود را بپرسید", lines=2)
140
+ response = gr.HTML(label="پاسخ", interactive=False) # تغییر از Textbox به HTML
141
+ submit_btn = gr.Button("ارسال سوال")
142
+
143
+ file = gr.File(label="📎 آپلود فایل", file_types=[".pdf"])
144
+ upload_status = gr.Textbox(label="وضعیت آپلود", interactive=False)
145
+ upload_btn = gr.Button("ارسال فایل")
146
+
147
+ upload_btn.click(save_uploaded_file, inputs=[file], outputs=[upload_status])
148
+ submit_btn.click(lambda q: format_response(chat_with_doc(q)), inputs=[query], outputs=[response])
149
+
150
+ demo.launch()