Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,10 +8,10 @@ import markdown
|
|
| 8 |
import nest_asyncio
|
| 9 |
nest_asyncio.apply()
|
| 10 |
|
| 11 |
-
|
| 12 |
-
# === Глобальная инициализация ===
|
| 13 |
embed_model = HuggingFaceEmbedding(model_name='intfloat/multilingual-e5-large-instruct')
|
| 14 |
Settings.embed_model = embed_model
|
|
|
|
| 15 |
Settings.llm = OpenRouter(
|
| 16 |
api_key=os.environ["OPENROUTER_API_KEY"],
|
| 17 |
model="qwen/qwen3-4b:free",
|
|
@@ -19,24 +19,11 @@ Settings.llm = OpenRouter(
|
|
| 19 |
context_window=20000,
|
| 20 |
)
|
| 21 |
|
| 22 |
-
# ===
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
try:
|
| 26 |
-
if not user_question.strip():
|
| 27 |
-
return "Ошибка: пожалуйста, введите ваш запрос."
|
| 28 |
-
|
| 29 |
-
storage_context = StorageContext.from_defaults(persist_dir="./storage")
|
| 30 |
-
index = load_index_from_storage(storage_context)
|
| 31 |
-
retriever = index.as_retriever(similarity_top_k=6)
|
| 32 |
-
nodes = retriever.retrieve(user_question)
|
| 33 |
-
|
| 34 |
-
context = "\n\n".join([node.get_content() for node in nodes]) if nodes else "Не найдено релевантных документов."
|
| 35 |
-
syst_prompt = f"""
|
| 36 |
Ты — эксперт по адаптации к изменениям климата.
|
| 37 |
У тебя есть база знаний с кейсами и нормативными документами.
|
| 38 |
Пользователь вводит запрос, связанный с климатическим риском в регионе или отрасли.
|
| 39 |
-
|
| 40 |
Твоя задача — на основе информации из базы знаний предложить 1–3 релевантных адаптационных мероприятия,
|
| 41 |
которые помогут снизить климатический риск, о котором спрашивает пользователь. Из базы знаний выбирай только те мероприятия, которые наиболее применимы в случае, описанном пользователем.
|
| 42 |
|
|
@@ -47,55 +34,70 @@ def get_facts(user_question: str) -> str:
|
|
| 47 |
- Адаптационный эффект
|
| 48 |
- Актуальность для региона (указать с учётом контекста запроса). Если регион не указан, считай, что задается вопрос по Тюменской области
|
| 49 |
- Ответственная организация (из региона)
|
| 50 |
-
|
| 51 |
2. Если источник данных, на которых ты основываешь ответ, известен (это URL и краткое название кейса),
|
| 52 |
добавь их **ниже таблицы** в виде списка ссылок:
|
| 53 |
`**Опорные источники:** [1] Название кейса - URL, [2] Название кейса - URL`
|
| 54 |
-
|
| 55 |
3. Пиши кратко, по существу, с акцентом на реальные, практические меры.
|
| 56 |
-
4. Если информация отсутствует — предложи логичные адаптационные меры на основе Приказа Минэкономразвития России от 13 мая 2021 г. № 267
|
|
|
|
| 57 |
|
| 58 |
Пример формата ответа:
|
| 59 |
-
|
| 60 |
| Наименование мероприятий | Митигационный эффект | Адаптационный эффект | Актуальность для Тобольского района | Ответственная организация |
|
| 61 |
|---------------------------|----------------------|----------------------|------------------------------------|----------------------------|
|
| 62 |
| Развитие городского электротранспорта | снижение эмиссии | повышение устойчивости транспортной инфраструктуры | актуально | городские власти |
|
| 63 |
| Перевод транспорта на газомоторное топливо | снижение эмиссии | рациональное использование ресурсов | реализуется частично | транспортные организации |
|
| 64 |
-
|
| 65 |
**Опорные источники:** [1] Кейс 12 - <https://example.com/case_12>
|
| 66 |
-
База знан��й:
|
| 67 |
-
{context}
|
| 68 |
-
Пользовательский вопрос: {user_question}
|
| 69 |
"""
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
response = Settings.llm.chat(messages)
|
| 75 |
-
|
|
|
|
|
|
|
| 76 |
return html
|
| 77 |
|
| 78 |
except Exception as e:
|
| 79 |
return f"Ошибка:\n{str(e)}"
|
| 80 |
-
|
| 81 |
-
response = Settings.llm.chat(messages)
|
| 82 |
-
return response.message.content
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
user_input = gr.Textbox(
|
| 88 |
label="Ваш запрос",
|
| 89 |
-
lines=
|
| 90 |
-
placeholder="
|
| 91 |
)
|
| 92 |
-
|
| 93 |
-
answer_output = gr.Markdown(label="Рекомендованные адаптационные мероприятия", height=300)
|
| 94 |
|
| 95 |
-
|
|
|
|
|
|
|
| 96 |
send_button.click(fn=get_facts, inputs=user_input, outputs=answer_output)
|
| 97 |
|
| 98 |
demo.launch()
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
demo.launch()
|
|
|
|
| 8 |
import nest_asyncio
|
| 9 |
nest_asyncio.apply()
|
| 10 |
|
| 11 |
+
# === 🔧 Глобальная инициализация ===
|
|
|
|
| 12 |
embed_model = HuggingFaceEmbedding(model_name='intfloat/multilingual-e5-large-instruct')
|
| 13 |
Settings.embed_model = embed_model
|
| 14 |
+
|
| 15 |
Settings.llm = OpenRouter(
|
| 16 |
api_key=os.environ["OPENROUTER_API_KEY"],
|
| 17 |
model="qwen/qwen3-4b:free",
|
|
|
|
| 19 |
context_window=20000,
|
| 20 |
)
|
| 21 |
|
| 22 |
+
# === 🧠 Системный промпт ===
|
| 23 |
+
SYSTEM_PROMPT = """
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
Ты — эксперт по адаптации к изменениям климата.
|
| 25 |
У тебя есть база знаний с кейсами и нормативными документами.
|
| 26 |
Пользователь вводит запрос, связанный с климатическим риском в регионе или отрасли.
|
|
|
|
| 27 |
Твоя задача — на основе информации из базы знаний предложить 1–3 релевантных адаптационных мероприятия,
|
| 28 |
которые помогут снизить климатический риск, о котором спрашивает пользователь. Из базы знаний выбирай только те мероприятия, которые наиболее применимы в случае, описанном пользователем.
|
| 29 |
|
|
|
|
| 34 |
- Адаптационный эффект
|
| 35 |
- Актуальность для региона (указать с учётом контекста запроса). Если регион не указан, считай, что задается вопрос по Тюменской области
|
| 36 |
- Ответственная организация (из региона)
|
|
|
|
| 37 |
2. Если источник данных, на которых ты основываешь ответ, известен (это URL и краткое название кейса),
|
| 38 |
добавь их **ниже таблицы** в виде списка ссылок:
|
| 39 |
`**Опорные источники:** [1] Название кейса - URL, [2] Название кейса - URL`
|
|
|
|
| 40 |
3. Пиши кратко, по существу, с акцентом на реальные, практические меры.
|
| 41 |
+
4. Если информация отсутствует — предложи логичные адаптационные меры на основе Приказа Минэкономразвития России от 13 мая 2021 г. № 267
|
| 42 |
+
«Об утверждении методических рекомендаций и показателей по вопросам адаптации к изменениям климата».
|
| 43 |
|
| 44 |
Пример формата ответа:
|
|
|
|
| 45 |
| Наименование мероприятий | Митигационный эффект | Адаптационный эффект | Актуальность для Тобольского района | Ответственная организация |
|
| 46 |
|---------------------------|----------------------|----------------------|------------------------------------|----------------------------|
|
| 47 |
| Развитие городского электротранспорта | снижение эмиссии | повышение устойчивости транспортной инфраструктуры | актуально | городские власти |
|
| 48 |
| Перевод транспорта на газомоторное топливо | снижение эмиссии | рациональное использование ресурсов | реализуется частично | транспортные организации |
|
|
|
|
| 49 |
**Опорные источники:** [1] Кейс 12 - <https://example.com/case_12>
|
|
|
|
|
|
|
|
|
|
| 50 |
"""
|
| 51 |
+
|
| 52 |
+
# === 🧩 Функция получения ответа ===
|
| 53 |
+
def get_facts(user_question: str) -> str:
|
| 54 |
+
try:
|
| 55 |
+
if not user_question.strip():
|
| 56 |
+
return "Пожалуйста, введите ваш запрос."
|
| 57 |
+
|
| 58 |
+
# Загружаем индекс
|
| 59 |
+
storage_context = StorageContext.from_defaults(persist_dir="./storage")
|
| 60 |
+
index = load_index_from_storage(storage_context)
|
| 61 |
+
retriever = index.as_retriever(similarity_top_k=4)
|
| 62 |
+
nodes = retriever.retrieve(user_question)
|
| 63 |
+
|
| 64 |
+
# Формируем контекст
|
| 65 |
+
context = "\n\n".join([node.get_content() for node in nodes]) if nodes else "Не найдено релевантных документов."
|
| 66 |
+
full_prompt = SYSTEM_PROMPT + f"\n\nКонтекст:\n{context}\n\nПользовательский запрос: {user_question}"
|
| 67 |
+
|
| 68 |
+
# Отправляем сообщение модели
|
| 69 |
+
messages = [ChatMessage(role="system", content=full_prompt)]
|
| 70 |
response = Settings.llm.chat(messages)
|
| 71 |
+
|
| 72 |
+
# Преобразуем markdown в HTML для красивого вывода таблицы
|
| 73 |
+
html = markdown.markdown(response.message.content, extensions=["tables", "fenced_code", "nl2br"])
|
| 74 |
return html
|
| 75 |
|
| 76 |
except Exception as e:
|
| 77 |
return f"Ошибка:\n{str(e)}"
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
+
|
| 80 |
+
# === 🎨 Интерфейс Gradio ===
|
| 81 |
+
with gr.Blocks(theme=gr.themes.Soft(), css="""
|
| 82 |
+
.output-box {
|
| 83 |
+
min-height: 400px;
|
| 84 |
+
overflow-y: auto;
|
| 85 |
+
border: 1px solid #ccc;
|
| 86 |
+
border-radius: 10px;
|
| 87 |
+
padding: 10px;
|
| 88 |
+
}
|
| 89 |
+
""") as demo:
|
| 90 |
+
gr.Markdown("# Информационная система для помощи в адаптации к климатическим рискам")
|
| 91 |
|
| 92 |
user_input = gr.Textbox(
|
| 93 |
label="Ваш запрос",
|
| 94 |
+
lines=4,
|
| 95 |
+
placeholder="Например: 'В Тюменской области риск паводка'"
|
| 96 |
)
|
|
|
|
|
|
|
| 97 |
|
| 98 |
+
answer_output = gr.HTML(label="Рекомендованные адаптационные мероприятия", elem_classes="output-box")
|
| 99 |
+
|
| 100 |
+
send_button = gr.Button("Получить рекомендации")
|
| 101 |
send_button.click(fn=get_facts, inputs=user_input, outputs=answer_output)
|
| 102 |
|
| 103 |
demo.launch()
|
|
|
|
|
|
|
|
|