diff --git a/src/app/api/soru/route.ts b/src/app/api/soru/route.ts index 592dc61..1aeba7a 100644 --- a/src/app/api/soru/route.ts +++ b/src/app/api/soru/route.ts @@ -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) => diff --git a/src/lib/ai/sohbet-gecmisi.ts b/src/lib/ai/sohbet-gecmisi.ts new file mode 100644 index 0000000..5f45e1f --- /dev/null +++ b/src/lib/ai/sohbet-gecmisi.ts @@ -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") })); +}