import os import gradio as gr from db import db from rag import process_query from llm import LLM from prompts import default_system_promot import re def init_db(): with open("sources.txt", encoding="utf-8") as f: urls = f.read().splitlines() db.add(urls) def get_llm(model): return LLM(model) def extract_json_and_clean_text(text): # print(text) # Регулярное выражение для поиска содержимого между и pattern = r"(```json.*?```)" # Ищем совпадения (re.DOTALL позволяет захватывать многострочные данные) match = re.search(pattern, text, re.DOTALL) if match: # Извлекаем найденный JSON как строку json_string = match.group(1).strip() # Удаляем JSON блок из исходного текста cleaned_text = re.sub(pattern, "", text, flags=re.DOTALL).strip() return cleaned_text, json_string else: print("JSON блок не найден в тексте.") return text.strip(), "" # Высота столбцов (в пикселях) COLUMN_HEIGHT = 280 NUM_LINES = 12 def tab1(): with gr.Tab("Анализ пресейлов"): # Создаем два столбца: левый для загрузки файлов, правый для системного промпта with gr.Row(): with gr.Column(scale=1): # Левый столбец file_input = gr.File( label="Прикрепите рассматриваемый запрос", ) with gr.Column(scale=2): # Правый столбец system_prompt_input = gr.Textbox( label="Системный промпт", placeholder="Введите системный промпт...", lines=NUM_LINES, # Количество строк зависит от доступной высоты max_lines=NUM_LINES, interactive=True, value=default_system_promot ) with gr.Row(): model = gr.Dropdown( choices=["mistral", "qwen2.5-vl-72b-instruct", "deepseek_v3", "llama-3.3-70b"], # Список строк для выбора label="Выберите модель", # Подпись к выпадающему списку multiselect=False # Если True, можно выбрать несколько значений ) temperature = gr.Slider( minimum=0, maximum=1, step=0.01, label="Температура", value=0, info="Увеличение гибридного поиска повышает креативность модели" ) alpha = gr.Slider( minimum=0, maximum=1, step=0.01, label="Альфа", value=0.5, info="Регулировка гибридного поиска" ) # Кнопка "Отправить" send_button = gr.Button("Отправить") # Текстовое поле для отображения результата # result_output = gr.Textbox(label="Результат", lines=5, interactive=False) # with gr.Accordion('Результат:', open=True): # result_output = gr.Markdown(value="Здесь будет представлен результат") # Группа с лейблом и рамкой with gr.Row(): with gr.Column(elem_classes="markdown-group", scale=2): gr.HTML("
Результат:
") # Лейбл внутри рамки with gr.Column(elem_classes="markdown-content"): result_output = gr.Markdown(value="Здесь будет представлен результат", min_height=200, show_copy_button=True) with gr.Column(elem_classes="markdown-group", scale=1): gr.HTML("
Json результат:
") # Лейбл внутри рамки with gr.Column(elem_classes="markdown-content"): json_output = gr.Markdown(value="Здесь будет представлен json", min_height=200, show_copy_button=True) def respond(file, system_prompt, model, temperature, alpha): llm = get_llm(model) llm_response = process_query(file, system_prompt, llm, temperature, alpha) return extract_json_and_clean_text(llm_response) # Привязываем кнопку к функции обработки send_button.click( respond, inputs=[file_input, system_prompt_input, model, temperature, alpha], outputs=[result_output, json_output] ) def add_new_source(): new_url = gr.Textbox( label="url нового источника", placeholder="Введите url нового источника...", lines=1, max_lines=1, interactive=True, info="Поддерживается парсинг только с сайта https://www.reksoft.ru" ) add_button = gr.Button("Добавить") def add_source(url): if url.startswith("https://www.reksoft.ru"): db.add([url]) gr.Success(f"{url} успешно добавлен") else: gr.Error("Ошибка: представленная ссылка не принадлежит https://www.reksoft.ru") return url add_button.click( add_source, inputs=new_url, outputs=new_url ) def get_sources(): ids = db.get_ids() str_ids = "" for source in ids: str_ids += f'* {source}\n' return f"""\ # Источники {str_ids}""" def tab2(): with gr.Tab("Источники") as dynamic_tab: add_new_source() markdown_output = gr.Markdown("Изначальное содержимое Markdown") dynamic_tab.select(get_sources, outputs=markdown_output) # Функция для чтения содержимого файла и возврата его как строки def read_file_content(file_path): try: with open(file_path, 'r', encoding='utf-8') as file: content = file.read() return content except FileNotFoundError: return "Файл не найден." except Exception as e: return f"Произошла ошибка: {str(e)}" def tab3(): with gr.Tab("Инфо"): gr.Markdown(read_file_content('info.md')) gr.Image("architecture.png") gr.Markdown(read_file_content('team.md')) css = """ .markdown-group { border: 1px solid #e0e0e0 !important; border-radius: 4px !important; margin: 16px 0 !important; position: relative !important; padding-top: 14px !important; # Место для лейбла } .markdown-label { position: absolute !important; top: 0px !important; left: 8px !important; background: white !important; padding: 0 4px !important; font-size: 14px !important; color: #6b6b6b !important; font-weight: 500 !important; } .markdown-content { padding: 12px !important; background: #f9f9f9 !important; }""" # Интерфейс Gradio with gr.Blocks(css=css) as demo: gr.Markdown("# Анализ тендерных заявок") with gr.Tabs(): tab1() tab2() tab3() init_db() # Запуск приложения demo.launch()