grantforge-api / backend /agents /research_agent.py
GrantForge Bot
Deploy sha-e5b5650bf293cf47c826e2624784ec3d4e385cc5 — source build (no GHCR)
247d24a
Raw
History Blame Contribute Delete
3.79 kB
import logging
import os
from typing import Optional, Dict
from langchain_core.messages import SystemMessage, HumanMessage
from core.llm_router import get_llm
try:
from tools.web_search import general_web_search
except ImportError:
from backend.tools.web_search import general_web_search
logger = logging.getLogger(__name__)
class ResearchAgent:
"""
Sub-Agent badawczy Projektu TITAN.
Zadaniem tego agenta jest przeszukiwanie sieci (OSINT / Web Search)
oraz interpretacja wyników w przypadku braku danych w dokumencie.
Zastępuje człowieka w trybie pełnej automatyzacji, znacznie zwiększając skuteczność.
"""
def __init__(self):
# Inicjalizacja LLM dla analizy wyników badawczych.
self.llm = get_llm(task_type="creative") # Używamy creative/standard
def deep_search(self, query: str, context: str) -> str:
"""
Głębokie poszukiwanie danych w zewnętrznych bazach i sieci,
oraz ich synteza przy użyciu LLM.
"""
logger.info(f"🔎 [Research Agent TITAN] Rozpoczęto głębokie wyszukiwanie dla: {query}")
# 1. Wykonanie rzeczywistego wyszukiwania w sieci
search_results = general_web_search(query)
# 2. Jeśli nie znaleziono lub brak klucza, zwracamy stosowną informację,
# ale możemy spróbować odpowiedzieć z wiedzy LLM z uwzględnieniem kontekstu.
if "Błąd" in search_results or "Brak klucza" in search_results:
logger.warning(f"[Research Agent TITAN] Problem z wyszukiwarką: {search_results}")
search_context = "Nie udało się pobrać aktualnych danych z sieci z powodu braku dostępu do API wyszukiwania."
else:
search_context = f"Wyniki wyszukiwania:\n{search_results}"
system_prompt = (
"Jesteś zaawansowanym Agentem Badawczym OSINT. Twoim zadaniem jest dostarczenie "
"wyczerpujących i merytorycznych informacji na podstawie podanego kontekstu projektu "
"oraz wyników wyszukiwania z sieci.\n\n"
"Zasady:\n"
"1. Twoim celem jest odpowiedź na brakujące zapytanie (pytanie o brakujące dane).\n"
"2. Wykorzystaj informacje z 'Wyników wyszukiwania', jeśli są dostępne.\n"
"3. Oprzyj się na 'Kontekście projektu', aby odpowiedź była dopasowana do specyfiki firmy i projektu.\n"
"4. Jeśli z danych sieciowych i kontekstu nie da się jednoznacznie określić faktów (np. precyzyjnego przychodu małej firmy), "
"zaproponuj profesjonalne i wiarygodne oszacowanie lub standardowe dla branży wartości rynkowe i zaznacz, że to szacunek, "
"aby wniosek dotacyjny mógł zostać wygenerowany jako pełny szkic (użyj znaczników np. [SZACOWANY_PRZYCHÓD: 1.5 mln PLN]).\n"
"5. Pisz wyłącznie w języku polskim, stylem profesjonalnym, odpowiednim do wniosków unijnych i biznesplanów."
)
human_content = f"Pytanie o brakujące dane: {query}\n\nKontekst projektu:\n{context}\n\n{search_context}"
try:
response = self.llm.invoke([
SystemMessage(content=system_prompt),
HumanMessage(content=human_content)
])
final_answer = response.content if hasattr(response, 'content') else str(response)
logger.info("[Research Agent TITAN] Zakończono syntezę wyników badawczych.")
return final_answer
except Exception as e:
logger.error(f"[Research Agent TITAN] Błąd generowania odpowiedzi przez LLM: {e}")
return f"Nie udało się wygenerować odpowiedzi analitycznej na temat: {query}. Spróbuj użyć [BRAK DANYCH]."
research_agent = ResearchAgent()