# app.py import os import sys import time import gradio as gr import requests from langchain.prompts import ChatPromptTemplate from langchain_community.llms import Ollama from datetime import datetime from func_ai import classify_comment, retrieve_from_vdb, analyze_sentiment, log_message as ai_log from func_facebook import ( get_page_id, has_page_replied, get_unanswered_comments, reply_comment, hide_negative_comments, log_message as fb_log ) # Инициализация переменных окружения VECTOR_API_URL = os.getenv('API_URL') def log_message(message): timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"[{timestamp}] {message}") # Шаблон для генерации ответов template = """ You are an assistant answering users' questions using the provided context. Your tasks: 1. **Brevity**: Respond concisely, using only relevant information from the context. 2. **Politeness**: Start your response with a greeting and maintain a respectful tone. 3. **Clarity**: Avoid unnecessary explanations and use simple language. 4. **Language of the response**: Detect the language of the user's comment and reply in the same language. 5. **Safety**: Do not use phrases like "according to the context" and remove any warnings. 6. **Accuracy**: Provide the user with only important and verified purchase links. {context} Question: {input} """ def delete_faiss_index(): log_message("Удаляем FAISS индекс.") try: response = requests.delete(f"{VECTOR_API_URL}/delete_index/") if response.status_code == 200: log_message("FAISS индекс успешно удален.") return "FAISS успешно удален." else: log_message(f"Ошибка при удалении FAISS индекса: {response.json().get('detail')}") return {"status": "error", "message": response.json().get("detail", "Ошибка при удалении FAISS индекса.")} except Exception as e: log_message(f"Ошибка при удалении FAISS индекса: {e}") return {"status": "error", "message": str(e)} def upload_file_vdb(file): log_message("Загружаем файл") API_URL = f"{VECTOR_API_URL}/upload/" file_path = file.name # Получаем имя файла file_name = os.path.basename(file_path) # Сохраняем загруженный файл во временное место temp_path = f"/tmp/{file_name}" try: with open(temp_path, 'wb') as f: f.write(file.read()) log_message(f"Файл сохранен во временное место: {temp_path}") # Отправляем файл в векторную базу данных with open(temp_path, 'rb') as f: files = {'file': (file_name, f)} response = requests.post(API_URL, files=files) # Удаляем временный файл os.remove(temp_path) log_message(f"Временный файл {temp_path} удален.") # Обработка ответа от сервера if response.status_code == 200: log_message("Файл успешно загружен.") return "Файл успешно загружен." else: log_message(f"Ошибка при загрузке файла: {response.json().get('detail')}") return f"Ошибка: {response.json().get('detail')}" except Exception as e: log_message(f"Ошибка при загрузке файла: {e}") return f"Ошибка: {str(e)}" def generate_response(user_query, llm): log_message(f"Генерация ответа на запрос: {user_query}") prompt = ChatPromptTemplate.from_template(template) documents = retrieve_from_vdb(user_query) context = "\n".join(documents) log_message(f"Контекст из базы данных: {context[:100]}...") full_prompt = prompt.format(context=context, input=user_query) try: response = llm.invoke(full_prompt) log_message(f"Сгенерированный ответ: {response}") return response except Exception as e: log_message(f"Ошибка при генерации ответа: {e}") return "Извините, возникла ошибка при обработке вашего запроса." def process_comments(ACCESS_TOKEN): log_message("Начинаем процесс скрытия отрицательных комментариев.") hidden_comments_data = hide_negative_comments(ACCESS_TOKEN) log_message(f"Количество постов с скрытыми комментариями: {len(hidden_comments_data)}") log_message("Получение неотвеченных комментариев.") posts_with_unanswered_comments = get_unanswered_comments(ACCESS_TOKEN) page_id = get_page_id(ACCESS_TOKEN) if not page_id: log_message("Не удалось получить ID страницы.") return {"status": "failed", "reason": "Не удалось получить ID страницы."} log_message(f"ID страницы: {page_id}") processed_posts = [] # Инициализируем модель Ollama try: llm = Ollama(model="llama3.1") log_message("Модель Ollama 'llama3.1' инициализирована.") except Exception as e: log_message(f"Ошибка инициализации модели Ollama: {e}") return {"status": "failed", "reason": "Ошибка инициализации модели AI."} for post_data in posts_with_unanswered_comments: post_id = post_data['post_id'] post_message = post_data['post_message'] unanswered_comments = post_data['unanswered_comments'] post_replies = [] for comment in unanswered_comments: message = comment['message'] log_message(f"Обработка комментария: {message}") classification = classify_comment(message) log_message(f"Классификация комментария: {classification}") if classification == "interrogative": response_message = generate_response(message, llm) log_message(f"Ответ на комментарий: {response_message}") success = reply_comment(comment_id=comment['id'], message=response_message, token=ACCESS_TOKEN) if success: post_replies.append({ 'comment_id': comment['id'], 'comment_message': comment['message'], 'reply_message': response_message }) processed_posts.append({ 'post_id': post_id, 'post_message': post_message, 'hidden_comments': next((item['hidden_comments'] for item in hidden_comments_data if item['post_id'] == post_id), []), 'replies': post_replies }) return { "status": "completed", "posts": processed_posts } def generate_response_interface(user_query, llm): return generate_response(user_query, llm) # Создание интерфейса Gradio with gr.Blocks() as demo: with gr.Tab("Главная страница"): gr.Markdown("# Facebook Comment Filter") token_input = gr.Textbox(label="Access Token") output_main = gr.JSON() process_btn = gr.Button("Процессировать комментарии") process_btn.click(process_comments, inputs=token_input, outputs=output_main) with gr.Tab("Загрузить данные"): gr.Markdown("# Отправь Excel файл") file_input = gr.File(label="Загрузите Excel файл (.xlsx)") output_second = gr.Text() second_page_btn = gr.Button("Отправить файл") second_page_btn.click(upload_file_vdb, inputs=file_input, outputs=output_second) delete_btn = gr.Button("Удалить FAISS индекс") delete_btn.click(delete_faiss_index, outputs=output_second) if __name__ == "__main__": demo.launch( debug=True, server_port=7860, server_name="0.0.0.0", )