34 lines
1.7 KiB
JavaScript
34 lines
1.7 KiB
JavaScript
/** 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}))};
|
||
}
|