Spaces:
Running
Running
| """Lepsza odpowiedź Matcher AI gdy baza naborów jest pusta.""" | |
| import logging | |
| from fastapi import Depends, HTTPException | |
| from endpoints.grants import router, MatchRequest, get_nabory, run_advanced_match_core, MATCH_FALLBACK_QUESTIONS, _rule_based_advanced_match_fallback | |
| from endpoints.projects import get_db | |
| from core.subscription.middleware import verify_token | |
| from core.projects.models import Project | |
| logger = logging.getLogger(__name__) | |
| _orig_route = None | |
| def apply_match_fix(): | |
| global _orig_route | |
| for route in list(router.routes): | |
| if getattr(route, "path", "") == "/match" and "POST" in getattr(route, "methods", set()): | |
| router.routes.remove(route) | |
| _orig_route = route | |
| break | |
| async def match_grants_fixed( | |
| request: MatchRequest, | |
| token_data: dict = Depends(verify_token), | |
| db=Depends(get_db), | |
| ): | |
| clerk_id = token_data.get("sub") | |
| project = db.query(Project).filter( | |
| Project.id == request.project_id, | |
| Project.clerk_user_id == clerk_id, | |
| ).first() | |
| if not project: | |
| raise HTTPException(status_code=404, detail="Projekt nie istnieje lub brak dostępu") | |
| nabory_list: list = [] | |
| try: | |
| nabory_resp = await get_nabory(force_refresh=False, db=db) | |
| nabory_list = nabory_resp.get("nabory", []) | |
| stats = nabory_resp.get("count", 0) | |
| if not nabory_list: | |
| return { | |
| "status": "ok", | |
| "project_id": request.project_id, | |
| "needs_more_info": True, | |
| "clarifying_questions": [ | |
| "Baza naborów jest pusta. Uruchom import: POST /api/admin/grants/import-wyszukiwarka " | |
| "lub skrypt scripts/import_wyszukiwarka.py z plikiem WYSZUKIWARKA." | |
| ], | |
| "matches": [], | |
| "catalog_empty": True, | |
| "hint": "Ustaw WYSZUKIWARKA_JSON=/ścieżka/do/dotacje-2026-06-21.json i zaimportuj katalog.", | |
| } | |
| result = await run_advanced_match_core( | |
| title=project.title or "", | |
| description=project.description or "Brak opisu", | |
| estimated_value=project.estimated_value or 0.0, | |
| external_context=project.external_context or {}, | |
| industry=project.industry if hasattr(project, "industry") else "", | |
| user_answers=request.user_answers or [], | |
| nabory_list=nabory_list, | |
| ) | |
| if not result.needs_more_info: | |
| external_context = project.external_context or {} | |
| external_context["ai_matches"] = [m.model_dump() for m in result.matches] | |
| if request.user_answers: | |
| external_context["ai_matches_qa_history"] = [ | |
| qa.model_dump() for qa in request.user_answers | |
| ] | |
| project.external_context = external_context | |
| db.commit() | |
| return { | |
| "status": "ok", | |
| "project_id": request.project_id, | |
| "needs_more_info": result.needs_more_info, | |
| "clarifying_questions": result.clarifying_questions, | |
| "matches": [m.model_dump() for m in result.matches], | |
| "nabory_in_catalog": stats, | |
| } | |
| except Exception as e: | |
| logger.error("Error in match_grants for project %s: %s", request.project_id, e, exc_info=True) | |
| try: | |
| fallback = _rule_based_advanced_match_fallback( | |
| project.title or "", | |
| project.description or "", | |
| project.external_context or {}, | |
| request.user_answers or [], | |
| nabory_list, | |
| ) | |
| return { | |
| "status": "ok", | |
| "project_id": request.project_id, | |
| "needs_more_info": fallback.needs_more_info, | |
| "clarifying_questions": fallback.clarifying_questions, | |
| "matches": [m.model_dump() for m in fallback.matches], | |
| "fallback_mode": "rule_based", | |
| "detail": str(e)[:200], | |
| } | |
| except Exception: | |
| return { | |
| "status": "error", | |
| "detail": f"Błąd generowania dopasowań przez AI: {str(e)}", | |
| "needs_more_info": True, | |
| "clarifying_questions": MATCH_FALLBACK_QUESTIONS, | |
| "matches": [], | |
| } | |
| logger.info("[grants_match_fix] POST /match patched with catalog-empty handling.") | |