feat: narrative "Dosya Özeti" report instead of field-by-field JSON

summarizeCase now produces a full Markdown narrative report (Olayın
Özeti, Yargılama Süreci ve Kararlar, Taraf İddia/Savunmaları, Önemli
Bulgular ve Belgeler, Sonuç) instead of short structured fields - the
iddianame pre-analysis (when found) still runs first and is fed in as
context. The raw AI text is stored as {ozet: string} rather than
JSON-parsed, since asking the model to escape a multi-paragraph report
inside JSON was fragile.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
mstfyldz
2026-08-09 20:09:31 +03:00
co-authored by Claude Sonnet 5
parent c939dcf564
commit 50f6cbb1b2
2 changed files with 60 additions and 28 deletions
+13 -17
View File
@@ -1,7 +1,7 @@
import { Response } from 'express';
import { supabase } from '../lib/supabase';
import { AuthenticatedRequest } from '../middleware/auth';
import { runDocumentAnalysis, runIddianameAnalysis } from './document.controller';
import { runIddianameAnalysis, runCaseNarrativeAnalysis } from './document.controller';
import { findOrCreateCaseByTitle } from '../lib/caseLookup';
export const createCase = async (req: AuthenticatedRequest, res: Response) => {
@@ -34,15 +34,15 @@ function normalizeTr(s: string): string {
return s.replace(/İ/g, 'i').replace(/I/g, 'i').toLowerCase();
}
// Dava dosyasındaki TÜM belgelerin çıkarılmış metnini birleştirip tek bir AI
// özeti üretir (Dosya Ayrıntı ekranındaki "Özet Hazırla" butonu). uploadDocument'ın
// aksine tek bir belgeye değil, dosyanın o anki tüm belgelerine bakıyor.
// Dava dosyasındaki TÜM belgelerin çıkarılmış metnini birleştirip kapsamlı, anlatı
// biçiminde bir "Dosya Özeti" raporu üretir (Dosya Ayrıntı ekranındaki "Özet Hazırla"
// butonu). uploadDocument'ın aksine tek bir belgeye değil, dosyanın o anki tüm
// belgelerine bakıyor.
//
// Dosyada bir iddianame varsa önce SADECE onun üzerinden dar kapsamlı bir ön
// çıkarım yapılıyor (isnat edilen suç, iddia özeti, kritik tarihler); genel
// değerlendirme bu ön çıkarımı bağlam olarak alıp tüm belgelerle birlikte
// üretiliyor — böylece iddianamedeki temel olgular genel değerlendirmenin
// başlangıç noktası oluyor, kaybolmuyor.
// çıkarım yapılıyor (isnat edilen suç, iddia özeti, kritik tarihler); anlatı
// raporu bu ön çıkarımı bağlam olarak alıp tüm belgelerle birlikte üretiliyor —
// böylece iddianamedeki temel olgular raporun başlangıç noktası oluyor.
//
// Not: "Bu dosyadaki tüm evraklar işlenene kadar bekle" kontrolü burada DEĞİL,
// frontend'de (CaseDetail) yapılıyor — çünkü eklentiden indirilip henüz OCR/kayıt
@@ -78,26 +78,22 @@ export const summarizeCase = async (req: AuthenticatedRequest, res: Response) =>
const iddianameResult = await runIddianameAnalysis(String(iddianameDoc.extracted_text));
iddianameJson = iddianameResult.summaryJson;
} catch (e) {
console.error('İddianame ön analizi başarısız, genel değerlendirmeye iddianamesiz devam ediliyor:', e);
console.error('İddianame ön analizi başarısız, rapora iddianamesiz devam ediliyor:', e);
}
}
// Tüm belgeleri modele gönderiyoruz; runDocumentAnalysis toplamı ~15000 karaktere
// kırpıyor, o yüzden belge sayısına göre kabaca dengeli bir pay ayırıyoruz.
// Tüm belgeleri modele gönderiyoruz; ~15000 karaktere kırpılıyor, o yüzden belge
// sayısına göre kabaca dengeli bir pay ayırıyoruz.
const perDocLimit = Math.max(1000, Math.floor(15000 / withText.length));
const combinedText = withText
.map((d) => `--- ${d.filename} ---\n${String(d.extracted_text).slice(0, perDocLimit)}`)
.join('\n\n');
const analysisInput = iddianameJson
? `İDDİANAME ÖN ANALİZİ (genel değerlendirmeyi buna dayandır):\n${JSON.stringify(iddianameJson)}\n\n---\n\nDOSYADAKİ TÜM BELGELER:\n${combinedText}`
? `İDDİANAME ÖN ANALİZİ (rapora bunu öncelikli bağlam olarak yansıt):\n${JSON.stringify(iddianameJson)}\n\n---\n\nDOSYADAKİ TÜM BELGELER:\n${combinedText}`
: combinedText;
const { summaryJson, aiModel } = await runDocumentAnalysis(analysisInput);
if (iddianameJson) {
summaryJson.isnatEdilenSuc = iddianameJson.isnatEdilenSuc || null;
summaryJson.iddianameOzeti = iddianameJson.iddiaOzeti || null;
}
const { summaryJson, aiModel } = await runCaseNarrativeAnalysis(analysisInput);
const { data: analysisRecord, error: analysisError } = await supabase
.from('analyses')