""" app/routers/ingest.py - DEBUG VERSION """ import os import time import logging from fastapi import APIRouter, HTTPException from pydantic import BaseModel from typing import Optional, List, Dict, Any from app.core.ingestion import IngestionService from app.core.retriever import Retriever from app.models.dto import QueryRequest logger = logging.getLogger(__name__) router = APIRouter() # --- DTOs --- class AnalyzeRequest(BaseModel): text: str type: str = "concept" class SaveRequest(BaseModel): markdown_content: str filename: Optional[str] = None folder: str = "00_Inbox" class SaveResponse(BaseModel): status: str file_path: str note_id: str stats: Dict[str, Any] # --- Endpoints --- @router.post("/analyze") async def analyze_draft(req: AnalyzeRequest): """ WP-11 Intelligence: Liefert Link-Vorschläge. DEBUG MODE: Threshold gesenkt, Logging erhöht. """ try: retriever = Retriever() suggestions = [] query_text = req.text[:400] logger.info(f"ANALYZING TEXT: '{query_text}' (Type: {req.type})") if not query_text.strip(): return {"suggestions": []} # Wir suchen hits_result = await retriever.search(QueryRequest(query=query_text, top_k=5, mode="hybrid")) logger.info(f"RETRIEVER FOUND: {len(hits_result.results)} raw hits") seen_titles = set() for hit in hits_result.results: # Titel holen title = hit.payload.get("title") or hit.payload.get("note_id") or hit.node_id # Logging für jeden Treffer logger.info(f" -> CHECK HIT: {title} | Score: {hit.total_score:.4f}") if not title or title in seen_titles: continue seen_titles.add(title) # Edge Logic edge_kind = "related_to" if req.type == "project": edge_kind = "depends_on" if req.type == "decision": edge_kind = "references" # --- ÄNDERUNG: THRESHOLD GESENKT --- # War vorher 0.65. Jetzt 0.3 für Tests. if hit.total_score > 0.3: suggestions.append({ "target_title": title, "target_id": hit.node_id, "suggested_markdown": f"[[rel:{edge_kind} {title}]]", "reason": f"Semantisch ähnlich ({hit.total_score:.2f})", "type": "semantic" }) else: logger.info(f" -> SKIPPED (Score too low)") logger.info(f"RETURNING {len(suggestions)} SUGGESTIONS") return {"suggestions": suggestions} except Exception as e: logger.error(f"Analyze failed: {e}", exc_info=True) raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}") @router.post("/save", response_model=SaveResponse) async def save_note(req: SaveRequest): """WP-11 Persistence""" try: vault_root = os.getenv("MINDNET_VAULT_ROOT", "./vault") abs_vault_root = os.path.abspath(vault_root) if not os.path.exists(abs_vault_root): os.makedirs(abs_vault_root, exist_ok=True) final_filename = req.filename if not final_filename: final_filename = f"draft_{int(time.time())}.md" ingest_service = IngestionService() logger.info(f"Saving {final_filename}") result = await ingest_service.save_and_index( markdown_content=req.markdown_content, filename=final_filename ) if result.get("status") == "error": raise HTTPException(status_code=500, detail=result.get("error")) return SaveResponse( status="success", file_path=result.get("file_path", "unknown"), note_id=result.get("note_id", "unknown"), stats=result.get("stats", {}) ) except HTTPException as he: raise he except Exception as e: logger.error(f"Save failed: {e}", exc_info=True) raise HTTPException(status_code=500, detail=f"Save failed: {str(e)}")