Upload 2 files
Browse files- app.py +103 -0
- requirements.txt +18 -0
app.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from llama_index.llms.openrouter import OpenRouter
|
| 4 |
+
from llama_index.core.llms import ChatMessage
|
| 5 |
+
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
|
| 6 |
+
from llama_index.core import Settings, StorageContext, load_index_from_storage
|
| 7 |
+
|
| 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 |
+
Settings.llm = OpenRouter(
|
| 15 |
+
api_key=os.environ["OPENROUTER_API_KEY"],
|
| 16 |
+
model="qwen/qwen3-4b:free",
|
| 17 |
+
max_tokens=10000,
|
| 18 |
+
context_window=20000,
|
| 19 |
+
)
|
| 20 |
+
system_prompt = """
|
| 21 |
+
Ты — эксперт по адаптации к изменениям климата.
|
| 22 |
+
У тебя есть база знаний с кейсами и нормативными документами.
|
| 23 |
+
Пользователь вводит запрос, связанный с климатическим риском в регионе или отрасли.
|
| 24 |
+
|
| 25 |
+
Твоя задача — на основе информации из базы знаний предложить 2–3 релевантных адаптационных мероприятия,
|
| 26 |
+
которые помогут снизить климатический риск, о котором спрашивает пользователь.
|
| 27 |
+
|
| 28 |
+
### Требования к ответу:
|
| 29 |
+
1. Представь результат **в виде Markdown-таблицы** с колонками:
|
| 30 |
+
- Наименование мероприятий
|
| 31 |
+
- Митигационный эффект
|
| 32 |
+
- Адаптационный эффект
|
| 33 |
+
- Актуальность для региона (указать с учётом контекста запроса). Если регион не указан, считай, что задается вопрос по Тюменской области
|
| 34 |
+
- Ответственная организация (из региона)
|
| 35 |
+
|
| 36 |
+
2. Если источник данных, на которых ты основываешь ответ, известен (это URL и краткое название кейса),
|
| 37 |
+
добавь их **ниже таблицы** в виде списка ссылок:
|
| 38 |
+
`**Опорные источники:** [1] Наименовавание мероприятий - URL, [2] Наименовавание мероприятий - URL`
|
| 39 |
+
|
| 40 |
+
3. Пиши кратко, по существу, с акцентом на реальные, практические меры.
|
| 41 |
+
4. Если информация отсутствует — предложи логичные адаптационные меры на основе Приказа Минэкономразвития России от 13 мая 2021 г. № 267 «Об утверждении методических рекомендаций и показателей по вопросам адаптации к изменениям климата».
|
| 42 |
+
|
| 43 |
+
Пример формата ответа:
|
| 44 |
+
|
| 45 |
+
| Наименование мероприятий | Митигационный эффект | Адаптационный эффект | Актуальность для Тобольского района | Ответственная организация |
|
| 46 |
+
|---------------------------|----------------------|----------------------|------------------------------------|----------------------------|
|
| 47 |
+
| Развитие городского электротранспорта | снижение эмиссии | повышение устойчивости транспортной инфраструктуры | актуально | городские власти |
|
| 48 |
+
| Перевод транспорта на газомоторное топливо | снижение эмиссии | рациональное использование ресурсов | реализуется частично | транспортные организации |
|
| 49 |
+
|
| 50 |
+
**Опорные источники:** [1] Наименовавание мероприятий - https://example.com/case_12
|
| 51 |
+
Приводи только те источники, которые используешь для формирования таблицы непосредственно. URL приводи строго такое же, как указано в базе знаний. Наименование мероприятий бери из базы знаний
|
| 52 |
+
Ответственную организацию в таблице указывай актуальную для региона, который пользователь указал в запросе
|
| 53 |
+
"""
|
| 54 |
+
|
| 55 |
+
# === Функция получения ответа ===
|
| 56 |
+
def get_facts(user_question: str) -> str:
|
| 57 |
+
try:
|
| 58 |
+
if not user_question.strip():
|
| 59 |
+
return "Ошибка: пожалуйста, введите ваш запрос."
|
| 60 |
+
|
| 61 |
+
storage_context = StorageContext.from_defaults(persist_dir="./storage")
|
| 62 |
+
index = load_index_from_storage(storage_context)
|
| 63 |
+
retriever = index.as_retriever(similarity_top_k=4)
|
| 64 |
+
nodes = retriever.retrieve(user_question)
|
| 65 |
+
|
| 66 |
+
context = "\n\n".join([node.get_content() for node in nodes]) if nodes else "Не найдено релевантных документов."
|
| 67 |
+
full_system_prompt = system_prompt + f"\n\nКонтекст:\n{context}"
|
| 68 |
+
|
| 69 |
+
messages = [
|
| 70 |
+
ChatMessage(role="system", content=full_system_prompt),
|
| 71 |
+
ChatMessage(role="user", content="Пользовательский запрос: " + user_question)
|
| 72 |
+
]
|
| 73 |
+
|
| 74 |
+
response = Settings.llm.chat(messages)
|
| 75 |
+
return response.message.content
|
| 76 |
+
|
| 77 |
+
except Exception as e:
|
| 78 |
+
return f"Ошибка:\n{str(e)}"
|
| 79 |
+
|
| 80 |
+
response = Settings.llm.chat(messages)
|
| 81 |
+
return response.message.content
|
| 82 |
+
|
| 83 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 84 |
+
gr.Markdown("# Информационная система для помощи в адаптации к климатическим рискам")
|
| 85 |
+
|
| 86 |
+
user_input = gr.Textbox(
|
| 87 |
+
label="Ваш запрос",
|
| 88 |
+
lines=4,
|
| 89 |
+
max_lines = 4,
|
| 90 |
+
placeholder="Введите свой запрос"
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
gr.Markdown("# Ответ")
|
| 94 |
+
answer_output = gr.Markdown(height=300)
|
| 95 |
+
send_button = gr.Button("Получить ответ")
|
| 96 |
+
|
| 97 |
+
send_button.click(
|
| 98 |
+
fn=get_facts,
|
| 99 |
+
inputs=user_input,
|
| 100 |
+
outputs=answer_output
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
llama-index
|
| 2 |
+
llama-index-llms-groq
|
| 3 |
+
groq
|
| 4 |
+
llama-index-embeddings-huggingface
|
| 5 |
+
nest-asyncio
|
| 6 |
+
qdrant_client
|
| 7 |
+
llama-index-vector-stores-qdrant
|
| 8 |
+
llama-index-embeddings-fastembed
|
| 9 |
+
fastembed
|
| 10 |
+
llama-index-vector-stores-faiss
|
| 11 |
+
gradio
|
| 12 |
+
faiss-cpu
|
| 13 |
+
pandas
|
| 14 |
+
llama-index-llms-openrouter
|
| 15 |
+
llama-index-embeddings-huggingface
|
| 16 |
+
python-docx
|
| 17 |
+
openpyxl
|
| 18 |
+
markdown
|