- Dodano skrypt cron do automatycznej ekstrakcji wiedzy (scripts/cron_extract_knowledge.py)
- Dodano panel deduplikacji faktów (/admin/zopk/knowledge/fact-duplicates)
- Dodano API i funkcje auto-weryfikacji encji i faktów
- Dodano panel Timeline ZOPK (/admin/zopk/timeline) z CRUD
- Rozszerzono dashboard bazy wiedzy o statystyki weryfikacji i przyciski auto-weryfikacji
- Dodano migrację 016_zopk_milestones.sql dla tabeli kamieni milowych
- Naprawiono duplikat modelu ZOPKMilestone w database.py
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Model używa entity_a_id/entity_b_id, nie source_entity_id/target_entity_id.
Naprawione miejsca:
- get_entity_merge_preview(): zliczanie relacji
- merge_entities(): przenoszenie relacji
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem: `:entity_json::jsonb` było interpretowane przez SQLAlchemy
jako parametr `:entity_json` z dodatkowym `:jsonb` (błąd składni SQL)
Rozwiązanie: Użycie CAST(:entity_json AS jsonb) zamiast ::jsonb
Naprawione miejsca:
- get_entity_merge_preview() - linia 1919
- merge_entities() - linia 1831
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Zmiana kolejności ORDER BY w find_duplicate_entities():
- Teraz: sim DESC, entity_type, mentions DESC
- Wcześniej: entity_type, mentions DESC, sim DESC
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem: ZOPKKnowledgeFact nie ma kolumn subject_entity_id i object_entity_id.
Zamiast tego używa entities_involved (JSONB array).
Zmiany:
- get_entity_merge_preview(): użycie JSONB @> query do liczenia faktów
- merge_entities(): użycie JSONB update do zamiany entity ID w facts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Nowe funkcje w zopk_knowledge_service.py:
- find_duplicate_entities() - wyszukiwanie podobnych encji (pg_trgm)
- merge_entities() - łączenie encji z transferem relacji
- get_entity_merge_preview() - podgląd przed połączeniem
Nowe endpointy w app.py:
- GET /admin/zopk/knowledge/duplicates - panel zarządzania duplikatami
- POST /api/zopk/knowledge/duplicates/preview - podgląd merge
- POST /api/zopk/knowledge/duplicates/merge - wykonanie merge
Nowy szablon:
- templates/admin/zopk_knowledge_duplicates.html - UI z kartami encji
Dodatkowo:
- Aktualizacja CLAUDE.md z procedurą wdrażania
- Skrypt scripts/run_migration.py do uruchamiania migracji SQL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Priorytet 1 - Panel admina bazy wiedzy ZOPK:
- /admin/zopk/knowledge - dashboard ze statystykami
- /admin/zopk/knowledge/chunks - lista chunks z filtrowaniem
- /admin/zopk/knowledge/facts - lista faktów z typami
- /admin/zopk/knowledge/entities - lista encji z mentions
- CRUD operacje: weryfikacja, usuwanie
Priorytet 2 - Poprawa jakości odpowiedzi NordaGPT:
- Linki markdown do źródeł w kontekście ZOPK
- Ulepszone formatowanie (bold, listy, nagłówki)
- Sekcja "Źródła" na końcu odpowiedzi
- Instrukcje w system prompt dla lepszej prezentacji
Priorytet 3 - Timeline ZOPK:
- Model ZOPKMilestone w database.py
- Migracja 016_zopk_milestones.sql z sample data
- Sekcja "Roadmapa ZOPK" na stronie /zopk
- Pionowa oś czasu z markerami lat
- Statusy: completed, in_progress, planned, delayed
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Dodano Server-Sent Events (SSE) dla śledzenia postępu w czasie rzeczywistym:
- Scraping treści artykułów
- Ekstrakcja wiedzy przez Gemini AI
- Generowanie embeddingów
Funkcje:
- Modal z paskiem postępu i statystykami
- Live log operacji z kolorowaniem statusów
- Podsumowanie na zakończenie (sukces/błędy/czas)
- Możliwość zamknięcia modalu po zakończeniu
Zmiany techniczne:
- 3 nowe SSE endpointy (/stream)
- ProgressUpdate dataclass w scraperze
- Callback pattern w batch_scrape, batch_extract, generate_chunk_embeddings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All 328 auto-extracted facts had is_verified=False, causing
empty results. Changed to confidence_score >= 0.3 filter instead.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated prompt to specify expected JSON structure for facts and entities
- Added 'text' field support in fact parsing (alongside 'full_text')
- Listed explicit type values for facts and entities
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Testing revealed that max_tokens=2000 parameter causes Gemini to block
requests with safety filters, even for safe content.
Removed max_tokens from generate_text() call - Gemini will use default.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Testing revealed that Gemini 2.5 safety filters block texts longer than
~2000 chars. Applied two fixes:
1. Truncate chunk text to 2000 chars in _extract_with_ai() as safety net
2. Reduce MAX_CHUNK_SIZE from 1000 to 500 tokens (~2000 chars)
This ensures all AI extraction requests stay within Gemini's safe limits.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The complex JSON schema with pipe characters was triggering Gemini 2.5's
safety filters. Simplified to minimal prompt that still produces valid output.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem: Gemini blokował ekstrakcję z artykułów o energetyce
Rozwiązanie: Bardziej neutralne sformułowania promptów
- Podkreślono że to analiza PUBLICZNYCH artykułów prasowych
- Usunięto wrażliwe słowa kluczowe (nuclear, defense)
- Zmieniono 'extract' na 'identify'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem: GeminiService.generate_text() nie obsługuje parametru system_prompt
Rozwiązanie: Połączono system_prompt z user_prompt w jeden full_prompt
Dotyczy: ekstrakcji faktów, encji i relacji z artykułów ZOPK
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>