fix(danisman): M3 (7) — modele giden pencere tutarlı olsun

Cevapsız kalmış (iade edilmiş) sorular art arda user mesajı olarak, sayıyla
kesilen pencere de danışman mesajıyla başlayarak gidiyordu. modelPenceresi
baştaki danışman mesajlarını atar, art arda aynı rolü tek mesajda birleştirir.
Pencere sorgusuna rowid sıralaması eklendi (created_at saniye çözünürlüklü).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-05 01:05:19 +03:00
parent 1191f16916
commit 08f4ec22b0
2 changed files with 35 additions and 9 deletions

View File

@@ -1,4 +1,4 @@
import { eq, desc } from "drizzle-orm";
import { eq, desc, sql } from "drizzle-orm";
import type { NextRequest } from "next/server";
import { getSession } from "@/lib/session";
import { appDb, schema } from "@/lib/appdb";
@@ -14,6 +14,7 @@ import { kullanicininRaporu, sohbetGecmisiGetir } from "@/features/rapor/rapor-q
import type { AracBaglami } from "@/lib/ai/araclar";
import { danismanAkisi } from "@/lib/ai/sohbet-akisi";
import { sistemPromptu } from "@/lib/ai/danisman-prompt";
import { modelPenceresi } from "@/lib/ai/sohbet-gecmisi";
import { profilGetir } from "@/lib/danisman-profil-db";
import { listeOzetiCikar } from "@/lib/ai/rapor";
import type { RaporSonuc } from "@/features/rapor/types/rapor";
@@ -109,7 +110,7 @@ export async function POST(request: NextRequest) {
.select()
.from(schema.chatMessages)
.where(eq(schema.chatMessages.userId, session.user.id))
.orderBy(desc(schema.chatMessages.createdAt))
.orderBy(desc(schema.chatMessages.createdAt), sql`rowid DESC`)
.limit(MAX_GECMIS),
appDb.query.user.findFirst({
where: eq(schema.user.id, session.user.id),
@@ -234,13 +235,9 @@ export async function POST(request: NextRequest) {
);
}
const mesajlar = [
...gecmis.map((m) => ({
role: m.role as "user" | "assistant",
content: m.content,
})),
{ role: "user" as const, content: mesaj },
];
// Cevapsız kalmış (iade edilmiş) sorular ve danışmanla başlayan pencere
// modele bozuk sıra göndermesin
const mesajlar = modelPenceresi(gecmis, mesaj);
const userId = session.user.id;
const cevabiKaydet = (metin: string) =>

View File

@@ -0,0 +1,29 @@
/**
* Danışman sohbet geçmişinin saf kuralları (api/soru/route.ts kullanır).
*
* Saf modül: DB'ye ve oturuma dokunmaz, Next dışından da çalışır.
*/
export type SohbetMesaji = { role: "user" | "assistant"; content: string };
/**
* Modele giden mesaj penceresi: kayıtlı geçmiş + yeni soru. Kayıt her zaman
* soru-cevap çifti değildir — hata/iade sonrası kullanıcı mesajı cevapsız
* kalır, pencere de sayıyla kesildiği için danışman mesajıyla başlayabilir.
* Burada düzeltilir: baştaki danışman mesajları atılır, art arda aynı rolden
* gelenler tek mesajda birleşir (yinelenen metin bir kez yazılır). Sonuç
* hep user ile başlar, roller sırayla değişir ve yeni soruyla biter.
*/
export function modelPenceresi(gecmis: SohbetMesaji[], yeniSoru: string): SohbetMesaji[] {
const gruplar: { role: SohbetMesaji["role"]; parcalar: string[] }[] = [];
for (const m of [...gecmis, { role: "user" as const, content: yeniSoru }]) {
const son = gruplar.at(-1);
if (!son && m.role === "assistant") continue;
if (son?.role === m.role) {
if (!son.parcalar.includes(m.content)) son.parcalar.push(m.content);
} else {
gruplar.push({ role: m.role, parcalar: [m.content] });
}
}
return gruplar.map((g) => ({ role: g.role, content: g.parcalar.join("\n\n") }));
}