File size: 3,811 Bytes
e9fbcf4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01190a5
e9fbcf4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9efd956
e9fbcf4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
01190a5
e9fbcf4
 
 
01190a5
e9fbcf4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import * as React from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import type { ModelDatabaseRow } from "@/types/local-frontier";

export type ModelDatabaseProps = {
  rows: readonly ModelDatabaseRow[];
};

function matchesSearch(row: ModelDatabaseRow, search: string): boolean {
  const query = search.trim().toLowerCase();
  return !query || row.searchText.includes(query);
}

function ModelRow({ row }: { row: ModelDatabaseRow }): React.JSX.Element {
  return (
    <TableRow>
      <TableCell>
        <a
          className="font-semibold text-foreground underline-offset-2 hover:underline"
          href={row.modelHref}
        >
          {row.id}
        </a>
        <span className="block text-muted-foreground">{row.name}</span>
        <span className="mt-1 inline-flex border border-border px-2 py-0.5 text-xs text-muted-foreground">
          {row.precision}
        </span>
      </TableCell>
      <TableCell>{row.downloads}</TableCell>
      <TableCell>
        <span className="text-foreground">{row.architecture}</span>
        {row.architectureDetail ? (
          <span className="block">{row.architectureDetail}</span>
        ) : null}
        <span className="mt-1 inline-flex border border-border px-2 py-0.5 text-xs">
          {row.adapterKind}
        </span>
      </TableCell>
      <TableCell>
        <span>{row.totalParams} total</span>
        <span className="block">{row.activeParams} active</span>
      </TableCell>
      <TableCell>
        <span>{row.residentFootprint}</span>
        <span className="block">
          {row.activeTrafficFloor} active traffic floor
        </span>
      </TableCell>
      <TableCell>{row.context}</TableCell>
      <TableCell>
        <Button asChild size="sm" variant="outline">
          <a href={row.compareHref}>Compare</a>
        </Button>
      </TableCell>
    </TableRow>
  );
}

function ModelTable({
  rows,
}: {
  rows: readonly ModelDatabaseRow[];
}): React.JSX.Element {
  if (!rows.length) {
    return (
      <div className="p-8 text-muted-foreground">
        No models match the current filters.
      </div>
    );
  }

  return (
    <Table className="min-w-[1060px]">
      <TableHeader>
        <TableRow>
          <TableHead>HF model</TableHead>
          <TableHead>Downloads</TableHead>
          <TableHead>Architecture</TableHead>
          <TableHead>Parameters</TableHead>
          <TableHead>Resident footprint</TableHead>
          <TableHead>Context</TableHead>
          <TableHead>Calculator</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map((row) => (
          <ModelRow key={row.id} row={row} />
        ))}
      </TableBody>
    </Table>
  );
}

export function ModelDatabase({ rows }: ModelDatabaseProps): React.JSX.Element {
  const [search, setSearch] = React.useState("");
  const filteredRows = rows.filter((row) => matchesSearch(row, search));

  return (
    <Card>
      <CardHeader>
        <CardTitle>Model Database</CardTitle>
      </CardHeader>
      <CardContent className="grid gap-4">
        <label className="grid gap-1.5">
          <span className="text-xs font-semibold text-muted-foreground">
            Search
          </span>
          <Input
            placeholder="Qwen/Qwen3.6-35B-A3B, MoE, 32B"
            type="search"
            value={search}
            onChange={(event) => {
              setSearch(event.currentTarget.value);
            }}
          />
        </label>

        <ModelTable rows={filteredRows} />
      </CardContent>
    </Card>
  );
}