CAPS04-FE-REFACTOR / resources /js /components /admin /admin-rag-summary.tsx
wepee's picture
fix: admin dashboard endpoint
45e7f4a
Raw
History Blame Contribute Delete
5.99 kB
import { Database, FileSliders, Search, Shield } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import type { RagConfig } from '@/types/admin';
function valueOrDash(value: unknown): string {
if (value === null || value === undefined || value === '') {
return '-';
}
if (typeof value === 'boolean') {
return value ? 'Ya' : 'Tidak';
}
return String(value);
}
function ConfigRows({
rows,
}: {
rows: Array<[label: string, value: unknown]>;
}) {
return (
<dl className="grid gap-3 text-sm">
{rows.map(([label, value]) => (
<div
className="flex items-start justify-between gap-4 rounded-lg border border-(--lecturer-border) px-3 py-2"
key={label}
>
<dt className="text-muted-foreground">{label}</dt>
<dd className="max-w-[60%] text-right font-medium break-words">
{valueOrDash(value)}
</dd>
</div>
))}
</dl>
);
}
export function AdminRagSummary({
ragConfig,
}: {
ragConfig?: RagConfig | null;
}) {
const llm = ragConfig?.llm_config ?? {};
const vectorDb = ragConfig?.vector_db ?? {};
const retrieval = ragConfig?.retrieval ?? {};
return (
<section className="grid gap-6 xl:grid-cols-2">
<Card className="border-(--lecturer-border) bg-(--lecturer-surface) xl:col-span-2">
<CardHeader className="gap-3">
<div className="flex items-center justify-between gap-3">
<span className="rounded-xl bg-[var(--lecturer-primary-soft)] p-3 text-[var(--lecturer-primary)]">
<FileSliders className="size-5" />
</span>
<Badge variant="outline">RAG</Badge>
</div>
<div>
<CardTitle>Konfigurasi RAG</CardTitle>
<CardDescription>
Path config: {ragConfig?.path ?? '-'}
</CardDescription>
</div>
</CardHeader>
</Card>
<Card className="border-(--lecturer-border) bg-(--lecturer-surface)">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Shield className="size-5 text-[var(--lecturer-primary)]" />
LLM
</CardTitle>
<CardDescription>Ringkasan model aktif.</CardDescription>
</CardHeader>
<CardContent>
<ConfigRows
rows={[
['Provider', llm.active_provider],
['Model', llm.active_model],
['Temperature', llm.temperature],
['Max Tokens', llm.max_tokens],
['Request Timeout', llm.request_timeout],
]}
/>
</CardContent>
</Card>
<Card className="border-(--lecturer-border) bg-(--lecturer-surface)">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Database className="size-5 text-[var(--lecturer-primary)]" />
VectorDB
</CardTitle>
<CardDescription>Ringkasan embedding dan chunk.</CardDescription>
</CardHeader>
<CardContent>
<ConfigRows
rows={[
['Embedding Model', vectorDb.embedding_model],
['Persist Path', vectorDb.persist_path],
['Chunk Size', vectorDb.chunk_size],
['Chunk Overlap', vectorDb.chunk_overlap],
]}
/>
</CardContent>
</Card>
<Card className="border-(--lecturer-border) bg-(--lecturer-surface) xl:col-span-2">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Search className="size-5 text-[var(--lecturer-primary)]" />
Retrieval
</CardTitle>
<CardDescription>
Ringkasan bobot dan batas konteks retrieval.
</CardDescription>
</CardHeader>
<CardContent>
<ConfigRows
rows={[
['Top K', retrieval.top_k],
['Max Context Chars', retrieval.max_context_chars],
['BM25 Weight', retrieval.bm25_weight],
['Dense Weight', retrieval.dense_weight],
['Lexical Weight', retrieval.lexical_weight],
[
'Similarity Threshold',
retrieval.similarity_threshold,
],
['History Turns', retrieval.history_turns],
[
'Candidate Pool Size',
retrieval.candidate_pool_size,
],
['Neighbor Window', retrieval.neighbor_window],
['Reranker Model', retrieval.reranker_model],
['Enable Reranker', retrieval.enable_reranker],
]}
/>
</CardContent>
</Card>
</section>
);
}