Preserve question source chunks and reject fabricated citations
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/** Lossless bounded chunks, including a short last clause and long unbroken lines. */
|
||||
export function questionChunks(value, target = 1200) {
|
||||
if (!Number.isInteger(target) || target < 32 || target > 1400) throw new Error('Geçersiz kaynak parçası boyutu.');
|
||||
const text = String(value ?? '');
|
||||
const chunks = [];
|
||||
let offset = 0;
|
||||
while (offset < text.length) {
|
||||
let end = Math.min(offset + target, text.length);
|
||||
if (end < text.length) {
|
||||
const segment = text.slice(offset, end);
|
||||
const boundary = Math.max(segment.lastIndexOf('\n'), segment.lastIndexOf(' '));
|
||||
if (boundary >= target / 2) end = offset + boundary + 1;
|
||||
// A Unicode surrogate pair is one character, never two source fragments.
|
||||
if (/[\uD800-\uDBFF]/.test(text[end - 1]) && /[\uDC00-\uDFFF]/.test(text[end])) end--;
|
||||
}
|
||||
chunks.push(text.slice(offset, end));
|
||||
offset = end;
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
/** Reject fabricated references rather than attaching unrelated fallback sources. */
|
||||
export function qualifyQuestionAnswer(result, selected) {
|
||||
if (typeof result?.cevap !== 'string' || !result.cevap.trim())
|
||||
throw new Error('Model geçerli bir yanıt üretmedi. Yeniden deneyin.');
|
||||
const cevap = result.cevap.trim();
|
||||
const cited = [...new Set([...cevap.matchAll(/\[(\d+)\]/g)].map(match => Number(match[1])))];
|
||||
if (!cited.length) throw new Error('Yanıt kaynak parçasına atıf içermiyor. Yeniden deneyin.');
|
||||
const available = new Map(selected.map(part => [part.n, part]));
|
||||
if (cited.some(id => !available.has(id)))
|
||||
throw new Error('Yanıttaki kaynak numarası incelenen parçalarla uyuşmuyor. Yeniden deneyin.');
|
||||
return {cevap, kaynaklar:cited.map(n => ({n, alinti:available.get(n).icerik}))};
|
||||
}
|
||||
Reference in New Issue
Block a user