File size: 9,249 Bytes
3ff18b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
import os
import shutil
import logging
import gradio as gr
from langchain_community.document_loaders import PyPDFLoader  # تغییر به PyPDFLoader
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.chat_models import ChatOpenAI

# تنظیمات لاگ‌گیری
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# تنظیمات مسیرها
UPLOAD_FOLDER = "uploaded_files"
DATABASE_FILE = "/home/user/app/vector_database"  # بدون پسوند .pkl
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# بررسی و بارگذاری دیتابیس برداری
def load_database():
    try:
        if os.path.exists(DATABASE_FILE):
            embeddings = OpenAIEmbeddings(openai_api_key=os.getenv("My_huggingface_key"))
            vector_db = FAISS.load_local(DATABASE_FILE, embeddings)
            logger.info(f"✅ دیتابیس بارگذاری شد: {DATABASE_FILE}")
            return vector_db
        else:
            logger.warning(f"❌ دیتابیس در مسیر `{DATABASE_FILE}` وجود ندارد.")
            return None
    except Exception as e:
        logger.error(f"❌ خطا در بارگذاری دیتابیس: {e}")
        return None

def save_database(vector_db):
    try:
        vector_db.save_local(DATABASE_FILE)
        logger.info(f"✅ دیتابیس ذخیره شد: {DATABASE_FILE}")
    except Exception as e:
        logger.error(f"❌ خطا در ذخیره دیتابیس: {e}")
        raise e

global_vector_db = load_database()

# پردازش و ذخیره‌سازی فایل‌های PDF
def process_and_store_pdfs(file_paths):
    texts = []
    for file_path in file_paths:
        try:
            logger.info(f"در حال پردازش فایل: {file_path}")
            if file_path.endswith(".pdf"):
                # استفاده از PyPDFLoader به جای PDFMinerLoader
                loader = PyPDFLoader(file_path)
                documents = loader.load()
                texts.extend(documents)
                logger.info(f"✅ تعداد صفحات پردازش شده: {len(documents)}")
            else:
                logger.warning(f"فرمت فایل {file_path} پشتیبانی نمی‌شود.")
        except Exception as e:
            logger.error(f"خطا در پردازش فایل {file_path}: {e}")

    try:
        logger.info("در حال ایجاد embeddings و ذخیره‌سازی در FAISS...")
        openai_api_key = os.getenv("My_huggingface_key")

        if not openai_api_key:
            logger.error("❌ کلید API مقداردهی نشده است!")
            raise ValueError("❌ کلید OpenAI API یافت نشد.")

        embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
        vector_db = FAISS.from_documents(texts, embeddings)
        logger.info(f"✅ ذخیره‌سازی در FAISS با موفقیت انجام شد. تعداد اسناد: {vector_db.index.ntotal}")
        return vector_db
    except Exception as e:
        logger.error(f"خطا در ایجاد embeddings یا ذخیره‌سازی در FAISS: {e}")
        return None

# پاسخ‌گویی بر اساس اسناد بارگذاری‌شده
def chat_with_doc(query):
    try:
        global global_vector_db
        if not global_vector_db:
            return "❌ لطفاً یک فایل مرتبط آپلود کنید."

        if not query.strip():
            return "❌ لطفاً سوال خود را وارد کنید."

        # بازیابی اسناد مرتبط
        retriever = global_vector_db.as_retriever(search_kwargs={"k": 5})
        docs = retriever.get_relevant_documents(query)
        
        # لاگ‌گیری برای بررسی اسناد بازیابی شده
        logger.info(f"تعداد اسناد بازیابی شده: {len(docs)}")
        for doc in docs:
            logger.info(f"سند بازیابی شده: {doc.page_content[:100]}...")  # نمایش بخشی از متن سند

        context = "\n\n".join([doc.page_content for doc in docs])

        if not context:
            return "هیچ اطلاعات مرتبطی یافت نشد."

        # استفاده از مدل gpt-3.5-turbo به جای gpt-4 (در صورت عدم دسترسی به GPT-4)
        llm = ChatOpenAI(model_name="gpt-3.5-turbo", openai_api_key=os.getenv("My_huggingface_key"))
        
        # ساختار درخواست ساده‌تر
        prompt = f"""سوال: {query}\n\nاطلاعات مرتبط:\n{context}\n\nلطفاً به سوال پاسخ دهید:"""
        response = llm.predict(prompt)

        final_response = f"پاسخ:\n{response}\n\nمنابع:\n"
        for doc in docs:
            final_response += f"- {doc.metadata.get('source', 'نامشخص')}, صفحه {doc.metadata.get('page', 'نامشخص')}\n"

        return final_response
    except Exception as e:
        logger.error(f"خطا در پاسخ‌گویی بر اساس سند: {e}")
        return f"❌ خطایی رخ داده است: {e}"

# ذخیره فایل آپلود شده
def save_uploaded_file(file):
    try:
        file_name = os.path.basename(file)
        file_path = os.path.join(UPLOAD_FOLDER, file_name)
        shutil.copy(file, file_path)

        global global_vector_db
        global_vector_db = process_and_store_pdfs([file_path])
        if global_vector_db:
            save_database(global_vector_db)

        return f"✅ فایل ذخیره شد: {file_path}"
    except Exception as e:
        return f"❌ خطا در ذخیره فایل: {e}"

# دباگ موقت
def debug_temp():
    debug_results = []

    # بررسی مقدار کلید API
    openai_api_key = os.getenv("My_huggingface_key")
    if openai_api_key:
        debug_results.append(f"✅ کلید API مقداردهی شده: {openai_api_key[:5]}********")
    else:
        debug_results.append("❌ کلید API مقداردهی نشده است!")

    # بررسی نسخه langchain_community
    try:
        import langchain_community
        version = langchain_community.__version__
        debug_results.append(f"✅ نسخه langchain_community: {version}")
    except Exception as e:
        debug_results.append(f"❌ خطا در بررسی نسخه langchain_community: {e}")

    # بررسی فایل‌های PDF در مسیر آپلود
    try:
        pdf_files = [f for f in os.listdir(UPLOAD_FOLDER) if f.endswith(".pdf")]
        if pdf_files:
            file_paths = [os.path.join(UPLOAD_FOLDER, f) for f in pdf_files]
            debug_results.append(f"✅ فایل‌های PDF در مسیر `{UPLOAD_FOLDER}`:")
            
            # بررسی تعداد صفحات هر فایل
            for file_path in file_paths:
                try:
                    loader = PyPDFLoader(file_path)  # استفاده از PyPDFLoader
                    documents = loader.load()
                    debug_results.append(f"   - {os.path.basename(file_path)}: {len(documents)} صفحه")
                except Exception as e:
                    debug_results.append(f"❌ خطا در بررسی صفحات {file_path}: {str(e)}")
        else:
            debug_results.append(f"❌ هیچ فایل PDF در مسیر `{UPLOAD_FOLDER}` وجود ندارد.")
    except Exception as e:
        debug_results.append(f"❌ خطا در بررسی پوشه `{UPLOAD_FOLDER}`: {e}")

    # بررسی وضعیت دیتابیس
    try:
        if os.path.exists(DATABASE_FILE):
            debug_results.append(f"✅ دیتابیس در مسیر `{DATABASE_FILE}` وجود دارد.")
            
            # بررسی تعداد اسناد ذخیره شده
            if global_vector_db:
                debug_results.append(f"   - تعداد اسناد در دیتابیس: {global_vector_db.index.ntotal}")
            else:
                debug_results.append("❌ دیتابیس در حافظه بارگذاری نشده است")
        else:
            debug_results.append(f"❌ دیتابیس در مسیر `{DATABASE_FILE}` وجود ندارد.")
    except Exception as e:
        debug_results.append(f"❌ خطا در بررسی دیتابیس: {e}")

    return "\n".join(debug_results)

# رابط کاربری با Gradio
with gr.Blocks() as demo:
    gr.Markdown("# هوش مصنوعی همراه کارشناسان توزیع برق ایران")

    query = gr.Textbox(label="سوال خود را بپرسید", lines=2)
    response = gr.Textbox(label="پاسخ", lines=10, interactive=False)
    submit_btn = gr.Button("ارسال سوال")

    file = gr.File(label="📎 آپلود فایل", file_types=[".pdf"])
    upload_status = gr.Textbox(label="وضعیت آپلود", interactive=False)
    upload_btn = gr.Button("ارسال فایل")

    debug_btn = gr.Button("🔍 بررسی دباگ موقت")
    debug_output = gr.Textbox(label="نتایج دباگ", lines=10, interactive=False)

    upload_btn.click(save_uploaded_file, inputs=[file], outputs=[upload_status])
    submit_btn.click(chat_with_doc, inputs=[query], outputs=[response])
    debug_btn.click(debug_temp, outputs=debug_output)

demo.launch()