Nefertury's picture
Update app.py
c0ff589 verified
Raw
History Blame
38 kB
import os
import requests
import json
import gradio as gr
import pandas as pd
import matplotlib.pyplot as plt
import pypdf
import warnings
from langchain_google_genai import ChatGoogleGenerativeAI
warnings.filterwarnings("ignore", category=UserWarning)
# --- 1. Настройка констант, API и LLM ---
print("--- Настройка API и LLM ---")
# Определяем константу здесь, чтобы она была доступна всегда
API_BASE_URL = "http://194.113.209.48:8000"
llm = None # Инициализируем llm как None на случай ошибки
try:
# Ключ считывается из "секретов", которые вы задали в настройках Space
GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
if GEMINI_API_KEY:
llm = ChatGoogleGenerativeAI(model="gemini-1.5-pro-latest", google_api_key=GEMINI_API_KEY, temperature=0.1)
print("✅ LLM настроена.")
else:
print("❌ ОШИБКА: Секрет 'GEMINI_API_KEY' не найден. Убедитесь, что он добавлен в настройках Space.")
except Exception as e:
print(f"❌ Произошла ошибка при настройке LLM: {e}")
# --- 3. Загрузка данных и контекста ---
# 3.1. Загружаем заранее проанализированный портфель из CSV
print("--- Загрузка данных портфеля ---")
try:
tagged_portfolio_df = pd.read_csv('sber_portfolio_analyzed5.csv')
tagged_portfolio_df['region_name'] = tagged_portfolio_df['region_name'].str.strip()
print(f"✅ Успешно загружен проанализированный портфель из {len(tagged_portfolio_df)} проектов.")
except FileNotFoundError:
print("❌ Ошибка: Файл 'sber_portfolio_analyzed5.csv' не найден. Возможно, нужно сначала запустить ячейку для генерации этого файла.")
tagged_portfolio_df = pd.DataFrame()
# 3.2. Извлекаем текст из PDF-отчета
print("--- Извлечение текста из PDF-отчета ---")
full_report_text = ""
try:
# Убедитесь, что имя файла верное и он загружен
with open('f356d44202ac9361579f509ebf965950.pdf', 'rb') as f:
reader = pypdf.PdfReader(f)
for page in reader.pages:
full_report_text += page.extract_text() + "\n"
print("✅ Текст из PDF-файла успешно извлечен.")
except Exception as e:
print(f"❌ Ошибка при чтении PDF-файла: {e}")
# 3.3. Загружаем некредитные продукты
print("--- Извлечение текста из каталога продуктов ---")
sber_products_text = ""
try:
# Убедитесь, что файл products.pdf загружен в ваш Space
with open('products.pdf', 'rb') as f:
reader = pypdf.PdfReader(f)
for page in reader.pages:
sber_products_text += page.extract_text() + "\n"
print("✅ Текст из PDF-файла (Каталог продуктов) успешно извлечен.")
except Exception as e:
print(f"❌ Ошибка при чтении PDF-файла (Каталог продуктов): {e}")
# 3.4. Загружаем справочники
print("--- Загрузка справочников ---")
try:
regions_response = requests.get(f"{API_BASE_URL}/api/regions")
regions_data = regions_response.json()
regions_list = sorted([item['name'] for item in regions_data])
print("✅ Справочник регионов загружен.")
except Exception as e:
print(f"❌ Не удалось загрузить справочник регионов: {e}")
regions_list = sorted(list(tagged_portfolio_df['region_name'].unique()))
# 3.5. Определяем константы (структура Наццелей) - ПОЛНАЯ ВЕРСИЯ
NATIONAL_GOALS_STRUCTURE = {
"Сохранение населения, укрепление здоровья и повышение благополучия людей, поддержка семьи": [
"2.а) повышение суммарного коэффициента рождаемости до 1,6 к 2030 году и до 1,8 к 2036 году",
"2.б) увеличение ожидаемой продолжительности жизни до 78 лет к 2030 году и до 81 года к 2036 году",
"2.в) обеспечение не ниже среднероссийских темпов повышения к 2030 году суммарного коэффициента рождаемости в отстающих субъектах РФ",
"2.г) снижение к 2036 году дифференциации показателей ожидаемой продолжительности жизни не менее чем на 25%",
"2.д) снижение к 2030 году суммарной продолжительности временной нетрудоспособности граждан",
"2.е) повышение к 2030 году уровня удовлетворенности граждан условиями для занятий физкультурой и спортом",
"2.ж) увеличение к 2030 году численности граждан, получающих услуги долговременного ухода, до 500 тыс. человек",
"2.з) повышение к 2030 году уровня удовлетворенности участников СВО условиями для медицинской реабилитации и трудоустройства",
"2.и) создание и запуск к 2030 году цифровой платформы по управлению здоровьем человека",
"2.к) снижение уровня бедности ниже 7% к 2030 году и ниже 5% к 2036 году, в т.ч. среди многодетных семей",
"2.л) снижение коэффициента Джини до 0,37 к 2030 году и до 0,33 к 2036 году",
"2.м) рост МРОТ к 2030 году более чем в два раза, не менее 35 тыс. рублей в месяц",
"2.н) утверждение в 2026 году новых систем оплаты труда работников бюджетной сферы"
],
"Реализация потенциала каждого человека, развитие его талантов, воспитание патриотичной и социально ответственной личности": [
"3.а) создание к 2030 году условий для воспитания гармонично развитой личности на основе традиционных ценностей",
"3.б) увеличение к 2030 году численности иностранных студентов до 500 тыс. человек",
"3.в) увеличение к 2030 году доли молодых людей, участвующих в проектах развития и воспитания, до 75%",
"3.г) увеличение к 2030 году доли молодых людей, верящих в самореализацию в России, до 85%",
"3.д) увеличение к 2030 году доли молодых людей в добровольческой деятельности до 45%",
"3.е) обеспечение к 2030 году функционирования эффективной системы выявления талантов у 100% обучающихся",
"3.ж) обеспечение продвижения традиционных ценностей в не менее чем 70% проектов в сфере культуры к 2030 году",
"3.з) повышение к 2030 году удовлетворенности граждан работой организаций культуры",
"3.и) формирование к 2030 году современной системы профразвития педагогических работников"
],
"Комфортная и безопасная среда для жизни": [
"4.а) улучшение качества среды для жизни в опорных населенных пунктах на 30% к 2030 году",
"4.б) обеспечение граждан жильем общей площадью не менее 33 кв. метров на человека к 2030 году",
"4.в) обновление к 2030 году жилищного фонда не менее чем на 20% по сравнению с 2019 годом",
"4.г) устойчивое сокращение непригодного для проживания жилищного фонда",
"4.д) повышение доступности жилья на первичном рынке",
"4.е) благоустройство не менее чем 30 тыс. общественных территорий к 2030 году",
"4.ж) реализация программы модернизации коммунальной инфраструктуры для 20 млн. человек к 2030 году",
"4.з) строительство и реконструкция не менее чем 2 тыс. объектов питьевого водоснабжения к 2030 году",
"4.и) рост энергоэффективности в ЖКХ и строительстве",
"4.к) обновление парка общественного транспорта до 85% от норматива к 2030 году",
"4.л) приведение в нормативное состояние 85% дорог агломераций и 60% региональных дорог к 2030 году",
"4.м) снижение смертности в ДТП в 1.5 раза к 2030 году",
"4.н) увеличение авиационной подвижности населения на 50% к 2030 году",
"4.о) капитальный ремонт всех нуждающихся зданий школ и детсадов до конца 2030 года",
"4.п) подключение к сетевому газу не менее 1,6 млн домовладений к 2030 году",
"4.р) оснащение 900 центров кинопоказа в малых населенных пунктах к 2030 году"
],
"Экологическое благополучие": [
"5.а) формирование экономики замкнутого цикла: 100% сортировка ТКО, захоронение не более 50%, вовлечение 25% отходов в оборот к 2030 году",
"5.б) снижение в два раза выбросов опасных загрязняющих веществ в городах с высоким уровнем загрязнения к 2036 году",
"5.в) ликвидация до конца 2030 года не менее 50 опасных объектов накопленного вреда",
"5.г) снижение к 2036 году в два раза объема неочищенных сточных вод",
"5.д) сохранение лесов, биоразнообразия и создание условий для экологического туризма"
],
"Устойчивая и динамичная экономика": [
"6.а) темп роста ВВП выше среднемирового, 4-е место в мире по ВВП по ППС к 2030 году",
"6.б) снижение доли импорта до 17% ВВП к 2030 году",
"6.в) увеличение объема инвестиций в основной капитал на 60% к 2030 году (относительно 2020)",
"6.г) рост доходов населения и пенсий не ниже уровня инфляции",
"6.д) реальный рост дохода на работника МСП в 1,2 раза выше роста ВВП",
"6.ж) вхождение в топ-25 стран мира по плотности роботизации к 2030 году",
"6.н) увеличение доли туристской отрасли в ВВП до 5% к 2030 году",
"6.о) прирост экспорта несырьевых неэнергетических товаров на две трети к 2030 году",
"6.п) увеличение производства продукции АПК на 25% к 2030 году (относительно 2021)",
"6.р) увеличение экспорта продукции АПК в 1.5 раза к 2030 году (относительно 2021)"
],
"Технологическое лидерство": [
"7.а) обеспечение технологической независимости (биоэкономика, БАС, ИИ, новые материалы и др.)",
"7.б) увеличение индекса производства в обрабатывающей промышленности на 40% к 2030 году (относительно 2022)",
"7.в) вхождение в топ-10 стран мира по объему научных исследований к 2030 году",
"7.г) увеличение внутренних затрат на исследования до 2% ВВП к 2030 году",
"7.д) увеличение доли отечественных высокотехнологичных товаров в 1.5 раза к 2030 году",
"7.е) увеличение выручки малых технологических компаний в 7 раз к 2030 году"
],
"Цифровая трансформация": [
"8.а) достижение 'цифровой зрелости' госуправления и ключевых отраслей экономики к 2030 году",
"8.б) формирование рынка данных",
"8.в) доступ к высокоскоростному интернету для 97% домохозяйств к 2030 году",
"8.г) рост инвестиций в отечественные ИТ-решения вдвое выше темпа роста ВВП",
"8.д) переход 80% организаций на российское ПО к 2030 году"
]
}
print("✅ Словарь НАЦЦЕЛЕЙ успешно загружен.")
# --- 4. Определение функций приложения ---
print("--- Определение функций приложения ---")
# (Здесь идут полные определения функций generate_regional_briefing, _find_relevant_goals, analyze_new_project)
# --- ФИНАЛЬНАЯ ВЕРСИЯ С ТАБЛИЧНЫМ ПРЕДСТАВЛЕНИЕМ АНАЛИЗА ---
def generate_regional_briefing(region_name, year):
print("---")
print(f"НОВЫЙ ЗАПРОС [Стратегический обзор]:")
print(f"Регион: {region_name}, Год: {year}")
print("---")
if not region_name or not year:
yield "Пожалуйста, выберите регион и год.", None, None
return
if not 'full_report_text' in globals() or not full_report_text:
yield "Ошибка: Текст отчета ESG-индекса не был загружен.", None, None
return
yield "<h3 style='margin-top: 20px;'>⏳ Готовлю финальный отчет, это может занять до 30 секунд...</h3>", None, None
try:
region_id = next((item['id'] for item in regions_data if item['name'] == region_name), None)
params = {"year": int(year)}
response = requests.get(f"{API_BASE_URL}/api/region-performance/{region_id}/all", params=params)
response.raise_for_status()
urfu_data_raw = response.json()
urfu_data_simplified = {indicator.get('name'): indicator.get('region_value') for indicator in urfu_data_raw.get('indicators', []) if indicator.get('name') and indicator.get('region_value') is not None}
except Exception as e:
yield f"Не удалось получить данные от API УрФУ. Ошибка: {e}", None, None
return
region_portfolio = tagged_portfolio_df[tagged_portfolio_df['region_name'] == region_name]
portfolio_summary = "В данном регионе у Сбера отсутствуют проекты из анализируемого портфеля."
fig = None
if not region_portfolio.empty:
total_investment = region_portfolio['amount_bln_rub'].sum()
project_count = len(region_portfolio)
SUMMARIZATION_THRESHOLD = 5
if 'mapped_goal' in region_portfolio.columns and not region_portfolio['mapped_goal'].isnull().all():
if project_count > SUMMARIZATION_THRESHOLD:
summary_parts = []
goal_groups = region_portfolio.groupby('mapped_goal')['amount_bln_rub'].sum().sort_values(ascending=False).reset_index()
for _, row in goal_groups.iterrows():
goal_name = row['mapped_goal']
goal_sum = row['amount_bln_rub']
project_examples = region_portfolio[region_portfolio['mapped_goal'] == goal_name]['project_goal'].head(2).tolist()
examples_text = ", ".join(project_examples)
# ИЗМЕНЕНИЕ: Формируем HTML-элемент списка <li> и используем <strong> для жирности
summary_parts.append(
f"<li><strong>{goal_name}</strong> ({goal_sum:.1f} млрд руб.), ключевые проекты: {examples_text}</li>"
)
# ИЗМЕНЕНИЕ: Собираем полный HTML-список <ul>...</ul>
summary_text = "<ul>" + "".join(summary_parts) + "</ul>"
portfolio_summary = (
f"Портфель Сбера в регионе составляет {total_investment:.1f} млрд руб. и включает проекты, распределенные по следующим национальным целям:{summary_text}"
)
else:
projects_list = [
f"'{row['project_goal']}' ({row['amount_bln_rub']:.1f} млрд руб.), направленный на достижение цели \"{row.get('mapped_goal', 'не определена')}\""
for _, row in region_portfolio.iterrows()
]
projects_text = " и ".join(projects_list)
portfolio_summary = (
f"Текущий портфель Сбера в регионе составляет {total_investment:.1f} млрд руб. "
f"и включает следующие ключевые проекты: {projects_text}."
)
else:
projects_list = [
f"'{row['project_goal']}' ({row['amount_bln_rub']:.1f} млрд руб.)"
for _, row in region_portfolio.iterrows()
]
projects_text = ", ".join(projects_list)
portfolio_summary = (
f"Текущий портфель Сбера в регионе составляет {total_investment:.1f} млрд руб. и включает следующие проекты: {projects_text}."
)
if 'mapped_goal' in region_portfolio.columns and not region_portfolio['mapped_goal'].isnull().all():
goal_distribution = region_portfolio.groupby('mapped_goal')['amount_bln_rub'].sum()
plot_data = goal_distribution.reset_index()
if plot_data is not None and not plot_data.empty:
fig, ax = plt.subplots(figsize=(10, 6)); bars = ax.bar(plot_data['mapped_goal'], plot_data['amount_bln_rub'], color='#4CAF50'); ax.bar_label(bars, fmt='%.0f', padding=3)
plt.xticks(rotation=45, ha="right", fontsize=9); plt.title(f"Распределение портфеля Сбера по Наццелям\nв регионе: {region_name}", fontsize=12)
plt.ylabel("Сумма, млрд руб.", fontsize=10); plt.grid(axis='y', linestyle='--', alpha=0.7); plt.tight_layout()
prompt = f"""
Твоя роль: Ведущий аналитик-стратег ESG-дирекции Сбера.
Твоя задача: Подготовить исчерпывающий и СТРУКТУРИРОВАННЫЙ аналитический отчет по региону, синтезируя информацию из предоставленных источников.
### ИСТОЧНИК 1: Статистические показатели по региону (от УрФУ)
Регион анализа: {region_name}
{json.dumps(urfu_data_simplified, ensure_ascii=False, indent=2)}
### ИСТОЧНИК 2: Полный текст отчета "ESG-индекс городов и регионов" (Сбер, ВЭБ.РФ)
```text
{full_report_text}
```
### ИСТОЧНИК 3: Данные по проектам в регионе
{portfolio_summary}
### ИСТОЧНИК 4: Каталог некредитных продуктов экосистемы Сбера
```text
{sber_products_text}
```
### ЗАДАЧА И СТРОГИЕ ПРАВИЛА:
1. Подготовь отчет в формате Markdown.
2. Сфокусируй детальный анализ ТОЛЬКО на двух Национальных целях: "Сохранение населения, укрепление здоровья и повышение благополучия людей, поддержка семьи" и "Комфортная и безопасная среда для жизни".
3. Относись ко всем данным как к реальным, не добавляй дисклеймеров.
4. Для раздела "Детальный анализ" **сгенерируй Markdown-таблицы**, как показано в шаблоне.
---
### Аналитический отчет: {region_name}, {year} год
**1. Обзор проектов в регионе**
* На основе ИСТОЧНИКА 3, опиши состав и объем проектов. Начинай с новой строки каждую новую Наццель и по ней проекты.
* **Задача для следующей строки:** На основе ИСТОЧНИКА 2, найди конкретные факты о регионе `{region_name}` (место в рейтинге, баллы, и т.д.).
* **Требование к форматированию:** Начни строку с "ESG-индекс городов и регионов Сбер - ВЭБ.РФ:". Сразу после этого, обычным черным текстом, продолжи своим аналитическим выводом.
**2. Детальный анализ по приоритетным Национальным целям**
* Для каждой из двух приоритетных Наццелей, создай подзаголовок и Markdown-таблицу по следующему образцу. Заполни 2-3 строки для каждой таблицы наиболее показательными данными.
**Национальная цель: "Сохранение населения, укрепление здоровья и повышение благополучия людей, поддержка семьи"**
| Показатель (данные УрФУ) | Значение в регионе | Влияние проектов Сбера |
| :--- | :--- | :--- |
| *[название показателя из ИСТОЧНИКА 1]* | *[значение из ИСТОЧНИКА 1]* | *[твой анализ ИСТОЧНИКА 3]* |
| *[название второго показателя]* | *[его значение]* | *[твой анализ]* |
**Национальная цель: "Комфортная и безопасная среда для жизни"**
| Показатель (данные УрФУ) | Значение в регионе | Влияние проектов Сбера |
| :--- | :--- | :--- |
| *[название показателя из ИСТОЧНИКА 1]* | *[значение из ИСТОЧНИКА 1]* | *[твой анализ ИСТОЧНИКА 3]* |
| *[название второго показателя]* | *[его значение]* | *[твой анализ]* |
**3. Стратегические рекомендации**
* **Шаг 1:** На основе табличного анализа, сформулируй 2-3 ключевых вывода и предложи конкретные **типы проектов** для инвестиций.
* **Шаг 2:** Внимательно изучи **ИСТОЧНИК 4 (Каталог некредитных продуктов)**.
* **Шаг 3:** Под твои рекомендации по типам проектов подбери 2-3 **наиболее релевантных продукта** из каталога.
* **Шаг 4:** Оформи рекомендации в виде списка. Сначала общая рекомендация, а под ней — подпункт "Рекомендуемые продукты Сбера:" с названиями продуктов.
"""
final_report = llm.invoke(prompt).content
yield final_report, fig, region_portfolio.drop(columns=['project_goal'], errors='ignore')
def _find_relevant_goals(project_description: str) -> list:
top_level_goals = list(NATIONAL_GOALS_STRUCTURE.keys())
prompt = f"""
Определи 1-3 наиболее релевантных национальных цели из списка для проекта. Верни ТОЛЬКО JSON-массив строк.
СПИСОК НАЦЦЕЛЕЙ: {json.dumps(top_level_goals, ensure_ascii=False)}
ОПИСАНИЕ ПРОЕКТА: "{project_description}"
Твой JSON-ответ:
"""
try:
response = llm.invoke(prompt)
return json.loads(response.content.strip().replace("```json", "").replace("```", ""))
except Exception:
return top_level_goals
def analyze_new_project(region_name, project_description):
print("---")
print(f"НОВЫЙ ЗАПРОС [Экспресс-оценка]:")
print(f"Регион: {region_name}")
print(f"Описание проекта: {project_description}")
print("---")
if not all([region_name, project_description]):
yield "Пожалуйста, выберите регион и опишите проект."
return
yield "<h3 style='margin-top: 20px;'>⏳ Этап 1/2: Определяю релевантные Наццели...</h3>"
relevant_goals_names = _find_relevant_goals(project_description)
relevant_goals_structure = {goal: NATIONAL_GOALS_STRUCTURE.get(goal, []) for goal in relevant_goals_names}
yield "<h3 style='margin-top: 20px;'>⏳ Этап 2/2: Готовлю детальный анализ, это может занять до 30 секунд...</h3>"
try:
region_id = next((item['id'] for item in regions_data if item['name'] == region_name), None)
params = {"year": 2024} # Можно использовать актуальный год
response = requests.get(f"{API_BASE_URL}/api/region-performance/{region_id}/all", params=params)
response.raise_for_status()
urfu_data_raw = response.json()
urfu_data_simplified = {indicator.get('name'): indicator.get('region_value') for indicator in urfu_data_raw.get('indicators', []) if indicator.get('name') and indicator.get('region_value') is not None}
except Exception as e:
yield f"Не удалось получить данные от API УрФУ. Ошибка: {e}"
return
goals_structure_str = json.dumps(relevant_goals_structure, ensure_ascii=False, indent=2)
# --- НАЧАЛО НОВОГО, РАСШИРЕННОГО ПРОМПТА ---
prompt = f"""
Твоя роль: Ведущий аналитик ESG-дирекции Сбера, обладающий глубокими знаниями в области национальных целей развития РФ.
Твоя задача: Подготовить ДЕТАЛЬНЫЙ и СТРУКТУРИРОВАННЫЙ аналитический отчет по новому инвестиционному проекту. Отчет должен быть выполнен в формате Markdown и содержать глубокий анализ, а не поверхностное описание.
### ВХОДНЫЕ ДАННЫЕ:
1. **Регион реализации:** {region_name}
2. **Описание проекта:** "{project_description}"
3. **Статистический контекст по региону (данные УрФУ):** {json.dumps(urfu_data_simplified, ensure_ascii=False, indent=2)}
4. **Структура релевантных Национальных целей и их задач:** {goals_structure_str}
### СТРОГИЕ ТРЕБОВАНИЯ К СТРУКТУРЕ И СОДЕРЖАНИЮ ОТЧЕТА:
**1. Краткое резюме проекта**
* Опиши суть проекта, его масштаб и основные цели.
**2. Анализ соответствия Национальным целям**
* Для КАЖДОЙ релевантной наццели из предоставленного списка:
* **Обоснуй, почему проект соответствует данной цели.** Четко свяжи деятельность по проекту с конкретными задачами (подпунктами) этой наццели.
* **Используй данные из статистического контекста (ВХОДНЫЕ ДАННЫЕ №3)**, чтобы показать АКТУАЛЬНОСТЬ проекта для региона. Например, если проект влияет на здравоохранение, приведи текущие показатели по ожидаемой продолжительности жизни или заболеваемости в регионе, чтобы подчеркнуть важность инвестиций.
**3. Оценка по ESG-критериям**
* **E (Environmental / Экология):** Оцени потенциальное положительное и отрицательное воздействие проекта на окружающую среду. Какие экологические риски и возможности он несет? (например, снижение выбросов, образование отходов, использование "зеленых" технологий).
* **S (Social / Социальная сфера):** Проанализируй социальный эффект. Создание рабочих мест (сколько, каких?), влияние на качество жизни, доступность услуг, поддержка местных сообществ.
* **G (Governance / Управление):** Опиши потенциальные управленческие аспекты. Необходимость взаимодействия с региональными властями, прозрачность реализации, работа с заинтересованными сторонами.
**4. Предварительные риски и рекомендации**
* На основе всего анализа, выдели 2-3 ключевых риска (технологических, социальных, регуляторных), на которые стоит обратить внимание.
* Дай 1-2 стратегические рекомендации по усилению положительного эффекта от проекта.
**5. Итоговое заключение**
* Сделай общий вывод о стратегической привлекательности проекта для банка с точки зрения вклада в устойчивое развитие и национальные приоритеты.
---
**Начинай твой отчет.**
"""
# --- КОНЕЦ НОВОГО ПРОМПТА ---
analysis_report = llm.invoke(prompt).content
yield analysis_report
# --- 5. Запуск веб-интерфейса Gradio ---
print("🚀 Запускаем Gradio-приложение...")
with gr.Blocks(theme=gr.themes.Soft(primary_hue="green", secondary_hue="lime"), css=".gradio-container {background-color: #f5f5f5} th { white-space: nowrap; }") as demo:
gr.Markdown(
"""<div style="text-align: center;"><img src="https://www.sberbank.com/common/img/uploaded/logo/logo_sber_main_2020_ru.svg" width="200">
<h1>Интерактивный дашборд "Горизонт PRO"</h1><p>Анализ вклада в достижение Национальных целей РФ 2030/2036</p></div>"""
)
with gr.Tabs():
with gr.TabItem("📈 Стратегический обзор региона"):
with gr.Row():
region_input_1 = gr.Dropdown(regions_list, label="Выберите регион")
year_input_1 = gr.Dropdown([2025, 2024, 2023, 2022], label="Выберите год", value=2024)
submit_button_1 = gr.Button("Сформировать стратегическую справку", variant="primary")
gr.Markdown("---")
output_report_1 = gr.Markdown(label="Аналитическая справка")
# Элементы создаются, но не отображаются в интерфейсе
# Это необходимо, чтобы функция click могла в них вернуть значения без ошибки.
output_plot_1 = gr.Plot(visible=False)
output_table_1 = gr.DataFrame(label="Проекты в портфеле", visible=False)
with gr.TabItem("🔎 Экспресс-оценка нового проекта"):
# --- ИЗМЕНЕНИЕ №1: Выносим текст примера в отдельную переменную ---
example_text = "Мусоросортировочный завод на 150 000 тонн стоимостью 3 млрд руб"
gr.Markdown("Введите описание нового инвестиционного проекта для анализа его соответствия Национальным целям и потребностям региона.")
region_input_2 = gr.Dropdown(regions_list, label="Выберите регион реализации проекта")
project_input_2 = gr.Textbox(lines=4, label="Опишите проект", placeholder=f"Пример: {example_text}")
# --- ИЗМЕНЕНИЕ №2: Добавляем две кнопки в одну строку ---
with gr.Row():
# Кнопка для вставки примера
example_button = gr.Button("✍️ Вставить пример", variant="secondary")
# Основная кнопка для анализа
submit_button_2 = gr.Button("Провести экспресс-оценку", variant="primary", scale=2) # scale=2 делает ее в 2 раза шире
gr.Markdown("---")
output_report_2 = gr.Markdown(label="Результат оценки")
# --- Привязка функций к кнопкам (остается без изменений) ---
submit_button_1.click(
fn=generate_regional_briefing,
inputs=[region_input_1, year_input_1],
outputs=[output_report_1, output_plot_1, output_table_1]
)
# --- ИЗМЕНЕНИЕ №3: Добавляем обработчик для новой кнопки ---
example_button.click(
fn=lambda: example_text, # Простая функция, которая просто возвращает текст примера
inputs=None, # У нее нет входных данных
outputs=project_input_2 # Результат (текст) отправляется в наше поле для ввода
)
submit_button_2.click(
fn=analyze_new_project,
inputs=[region_input_2, project_input_2],
outputs=[output_report_2]
)
demo.launch(share=True, debug=True)