feat: add digital-intern live-qa endpoints for pinpoint hearing assistance
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { supabase } from '../lib/supabase';
|
import { supabase } from '../lib/supabase';
|
||||||
import { AuthenticatedRequest } from '../middleware/auth';
|
import { AuthenticatedRequest } from '../middleware/auth';
|
||||||
import { runIddianameAnalysis, runCaseNarrativeAnalysis, runStatementAnalysis, runDeficiencyAnalysis, runStrategyAnalysis, runMediationAnalysis } from './document.controller';
|
import { runIddianameAnalysis, runCaseNarrativeAnalysis, runStatementAnalysis, runDeficiencyAnalysis, runStrategyAnalysis, runMediationAnalysis, runDigitalInternQa } from './document.controller';
|
||||||
import { findOrCreateCaseByTitle } from '../lib/caseLookup';
|
import { findOrCreateCaseByTitle } from '../lib/caseLookup';
|
||||||
|
|
||||||
export const createCase = async (req: AuthenticatedRequest, res: Response) => {
|
export const createCase = async (req: AuthenticatedRequest, res: Response) => {
|
||||||
@@ -385,3 +385,51 @@ export const deleteCase = async (req: AuthenticatedRequest, res: Response) => {
|
|||||||
res.status(500).json({ error: error.message || 'Internal Server Error' });
|
res.status(500).json({ error: error.message || 'Internal Server Error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const analyzeDigitalIntern = async (req: AuthenticatedRequest, res: Response) => {
|
||||||
|
try {
|
||||||
|
const { caseId } = req.params;
|
||||||
|
const { question, query } = req.body || {};
|
||||||
|
const questionToUse = question || query;
|
||||||
|
|
||||||
|
if (!caseId) {
|
||||||
|
return res.status(400).json({ error: 'Geçersiz caseId' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!questionToUse || !String(questionToUse).trim()) {
|
||||||
|
return res.status(400).json({ error: 'Soru (question) girmelisiniz.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: docs, error: docsError } = await supabase
|
||||||
|
.from('documents')
|
||||||
|
.select('filename, extracted_text')
|
||||||
|
.eq('case_id', caseId)
|
||||||
|
.order('uploaded_at', { ascending: true });
|
||||||
|
if (docsError) throw docsError;
|
||||||
|
|
||||||
|
const targetDocs = (docs || []).filter(d => d.extracted_text && String(d.extracted_text).trim());
|
||||||
|
|
||||||
|
if (targetDocs.length === 0) {
|
||||||
|
return res.status(400).json({ error: 'Bu dosyada arama yapılabilecek evrak bulunamadı.' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const perDocLimit = Math.max(1000, Math.floor(30000 / targetDocs.length));
|
||||||
|
const combinedText = targetDocs
|
||||||
|
.map((d) => `--- ${d.filename} ---\n${String(d.extracted_text).slice(0, perDocLimit)}`)
|
||||||
|
.join('\n\n');
|
||||||
|
|
||||||
|
const analysisInput = `Aşağıdaki belgeler dava dosyasına aittir:\n\n${combinedText}`;
|
||||||
|
|
||||||
|
const { summaryJson, aiModel } = await runDigitalInternQa(analysisInput, questionToUse);
|
||||||
|
|
||||||
|
// İsteğe bağlı olarak arama sonucunu da 'analyses' tablosuna kaydet
|
||||||
|
await supabase
|
||||||
|
.from('analyses')
|
||||||
|
.insert([{ case_id: caseId, document_id: null, summary_json: { digitalInternResult: summaryJson, question: questionToUse }, model_used: aiModel }]);
|
||||||
|
|
||||||
|
res.json({ result: summaryJson, modelUsed: aiModel });
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('Digital Intern Error:', error);
|
||||||
|
res.status(500).json({ error: error.message || 'Internal Server Error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -564,3 +564,31 @@ export const uploadDocument = async (req: AuthenticatedRequest, res: Response) =
|
|||||||
res.status(500).json({ error: error.message || 'Internal Server Error' });
|
res.status(500).json({ error: error.message || 'Internal Server Error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Dijital Stajyer (Duruşma Asistanı - Canlı ve Nokta Atışı Soru/Cevap)
|
||||||
|
export async function runDigitalInternQa(combinedText: string, question: string): Promise<{ summaryJson: any; aiModel: string }> {
|
||||||
|
const prompt = `Sen duruşma salonundaki avukatın yanında duran, saniyeler içinde nokta atışı cevap veren kıdemli DİJİTAL STAJYERSİN.
|
||||||
|
|
||||||
|
AVUKATIN SORUSU: "${question}"
|
||||||
|
|
||||||
|
GÖREVİN & SIKI İLKELERİN:
|
||||||
|
1. Duruşma anında avukatın saniyeler içinde okuyabileceği NOKTA ATIŞI ve NET cevabı ver.
|
||||||
|
2. Uzun giriş paragrafı, merhaba mesajı veya lakırdı KESİNLİKLE YASAKTIR. Doğrudan sonuca gir.
|
||||||
|
3. Bulduğun veriyi (Tarih, Saat, Belge Adı/No, İsim, Tutar, Sayfa) açıkça yaz.
|
||||||
|
4. Aranan bilgi dava evraklarında açıkça yer almıyorsa: "found": false yaz ve "Bu bilgi dosyadaki evraklarda bulunmamaktadır" de.
|
||||||
|
|
||||||
|
ÇIKTI FORMATI (SADECE GEÇERLİ JSON):
|
||||||
|
{
|
||||||
|
"found": true,
|
||||||
|
"answer": "📌 12 Ekim 2021 tarihinde düzenlenen Marmara Devlet Hastanesi Adli Muayene Raporu'nda altta kalça kırığı tespit edilmiştir.",
|
||||||
|
"dateInfo": "12 Ekim 2021",
|
||||||
|
"documentRef": "Marmara Devlet Hastanesi Adli Muayene Raporu (Belge No: 45)",
|
||||||
|
"exactExcerpt": "Dosyadan alınan birebir pasaj veya ilgili cümle...",
|
||||||
|
"confidenceScore": "%95"
|
||||||
|
}
|
||||||
|
|
||||||
|
Sadece ve sadece JSON döndür, kod bloğu işareti (\`\`\`) veya başka bir açıklama ekleme.`;
|
||||||
|
|
||||||
|
const { resultJson, aiModel } = await callAiModel(prompt, combinedText);
|
||||||
|
return { summaryJson: resultJson, aiModel };
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { requireAuth } from '../middleware/auth';
|
import { requireAuth } from '../middleware/auth';
|
||||||
import { createCase, deleteCase, summarizeCase, updateCaseParties, analyzeStatements, analyzeDeficiencies, analyzeStrategy, analyzeMediation } from '../controllers/case.controller';
|
import { createCase, deleteCase, summarizeCase, updateCaseParties, analyzeStatements, analyzeDeficiencies, analyzeStrategy, analyzeMediation, analyzeDigitalIntern } from '../controllers/case.controller';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
@@ -15,6 +15,8 @@ router.post('/:caseId/analyze-strategy', requireAuth, analyzeStrategy);
|
|||||||
router.post('/:caseId/strategy', requireAuth, analyzeStrategy);
|
router.post('/:caseId/strategy', requireAuth, analyzeStrategy);
|
||||||
router.post('/:caseId/analyze-mediation', requireAuth, analyzeMediation);
|
router.post('/:caseId/analyze-mediation', requireAuth, analyzeMediation);
|
||||||
router.post('/:caseId/mediation', requireAuth, analyzeMediation);
|
router.post('/:caseId/mediation', requireAuth, analyzeMediation);
|
||||||
|
router.post('/:caseId/digital-intern', requireAuth, analyzeDigitalIntern);
|
||||||
|
router.post('/:caseId/live-qa', requireAuth, analyzeDigitalIntern);
|
||||||
router.post('/parties', requireAuth, updateCaseParties);
|
router.post('/parties', requireAuth, updateCaseParties);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
Reference in New Issue
Block a user