Spaces:
Sleeping
Sleeping
File size: 5,990 Bytes
53a811b 1e5ae4b 53a811b 1e5ae4b 45e7f4a 1e5ae4b 53a811b 1e5ae4b 53a811b 1e5ae4b 53a811b 1e5ae4b 53a811b 1e5ae4b 45e7f4a 1e5ae4b 53a811b 1e5ae4b 53a811b 1e5ae4b 53a811b 1e5ae4b 53a811b 1e5ae4b 53a811b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 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>
);
}
|