Presidentlin
commited on
Commit
•
35a1853
1
Parent(s):
4060e49
- src/App.tsx +73 -16
- src/lib/data.ts +1 -1
src/App.tsx
CHANGED
@@ -29,10 +29,11 @@ const App: React.FC = () => {
|
|
29 |
const [selectedProviders, setSelectedProviders] = useState<string[]>([])
|
30 |
const [selectedModels, setSelectedModels] = useState<string[]>([])
|
31 |
const [expandedProviders, setExpandedProviders] = useState<string[]>([])
|
|
|
32 |
|
33 |
useEffect(() => {
|
34 |
setData(mockData)
|
35 |
-
setComparisonModels(['OpenAI:GPT-4o', 'Anthropic:Claude 3.5 (Sonnet)', 'Google:Gemini 1.5 Pro'])
|
36 |
}, [])
|
37 |
|
38 |
const calculatePrice = (price: number, tokens: number): number => {
|
@@ -50,6 +51,45 @@ const App: React.FC = () => {
|
|
50 |
}))
|
51 |
.filter((provider) => provider.models.length > 0)
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
console.log(filteredData)
|
54 |
|
55 |
const toggleProviderExpansion = (provider: string) => {
|
@@ -145,10 +185,26 @@ const App: React.FC = () => {
|
|
145 |
<Table>
|
146 |
<TableHeader>
|
147 |
<TableRow>
|
148 |
-
<TableHead>
|
149 |
-
|
150 |
-
|
151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
<TableHead>Total Price</TableHead>
|
153 |
{comparisonModels.map((model) => (
|
154 |
<TableHead key={model} colSpan={2}>
|
@@ -191,7 +247,7 @@ const App: React.FC = () => {
|
|
191 |
</TableRow>
|
192 |
</TableHeader>
|
193 |
<TableBody>
|
194 |
-
{
|
195 |
provider.models.map((model) => (
|
196 |
<TableRow key={`${provider.provider}-${model.name}`}>
|
197 |
<TableCell>
|
@@ -217,13 +273,12 @@ const App: React.FC = () => {
|
|
217 |
return [
|
218 |
<TableCell
|
219 |
key={`${comparisonModel}-input`}
|
220 |
-
className={`${
|
221 |
-
|
222 |
-
|
223 |
-
: parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) > 0
|
224 |
? 'bg-red-100'
|
225 |
: ''
|
226 |
-
|
227 |
>
|
228 |
{`${provider.provider}:${model.name}` === comparisonModel
|
229 |
? '0.00%'
|
@@ -231,13 +286,12 @@ const App: React.FC = () => {
|
|
231 |
</TableCell>,
|
232 |
<TableCell
|
233 |
key={`${comparisonModel}-output`}
|
234 |
-
className={`${
|
235 |
-
|
236 |
-
|
237 |
-
: parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) > 0
|
238 |
? 'bg-red-100'
|
239 |
: ''
|
240 |
-
|
241 |
>
|
242 |
{`${provider.provider}:${model.name}` === comparisonModel
|
243 |
? '0.00%'
|
@@ -250,6 +304,9 @@ const App: React.FC = () => {
|
|
250 |
)}
|
251 |
</TableBody>
|
252 |
</Table>
|
|
|
|
|
|
|
253 |
</CardContent>
|
254 |
</Card>
|
255 |
)
|
|
|
29 |
const [selectedProviders, setSelectedProviders] = useState<string[]>([])
|
30 |
const [selectedModels, setSelectedModels] = useState<string[]>([])
|
31 |
const [expandedProviders, setExpandedProviders] = useState<string[]>([])
|
32 |
+
const [sortConfig, setSortConfig] = useState<{ key: string, direction: string } | null>(null)
|
33 |
|
34 |
useEffect(() => {
|
35 |
setData(mockData)
|
36 |
+
setComparisonModels(['OpenAI:GPT-4o-mini', 'Anthropic:Claude 3.5 (Sonnet)', 'Google:Gemini 1.5 Pro'])
|
37 |
}, [])
|
38 |
|
39 |
const calculatePrice = (price: number, tokens: number): number => {
|
|
|
51 |
}))
|
52 |
.filter((provider) => provider.models.length > 0)
|
53 |
|
54 |
+
const sortedData = React.useMemo(() => {
|
55 |
+
let sortableData = [...filteredData];
|
56 |
+
if (sortConfig !== null) {
|
57 |
+
if (sortConfig.key === 'provider') {
|
58 |
+
sortableData.sort((a, b) => {
|
59 |
+
if (a.provider < b.provider) {
|
60 |
+
return sortConfig.direction === 'ascending' ? -1 : 1;
|
61 |
+
}
|
62 |
+
if (a.provider > b.provider) {
|
63 |
+
return sortConfig.direction === 'ascending' ? 1 : -1;
|
64 |
+
}
|
65 |
+
return 0;
|
66 |
+
});
|
67 |
+
} else if (sortConfig.key === 'model' || sortConfig.key === 'inputPrice' || sortConfig.key === 'outputPrice') {
|
68 |
+
sortableData.forEach(provider => {
|
69 |
+
provider.models.sort((a, b) => {
|
70 |
+
if (a[sortConfig.key] < b[sortConfig.key]) {
|
71 |
+
return sortConfig.direction === 'ascending' ? -1 : 1;
|
72 |
+
}
|
73 |
+
if (a[sortConfig.key] > b[sortConfig.key]) {
|
74 |
+
return sortConfig.direction === 'ascending' ? 1 : -1;
|
75 |
+
}
|
76 |
+
return 0;
|
77 |
+
});
|
78 |
+
});
|
79 |
+
}
|
80 |
+
}
|
81 |
+
return sortableData;
|
82 |
+
}, [filteredData, sortConfig]);
|
83 |
+
|
84 |
+
const requestSort = (key: string) => {
|
85 |
+
let direction = 'ascending';
|
86 |
+
if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') {
|
87 |
+
direction = 'descending';
|
88 |
+
}
|
89 |
+
setSortConfig({ key, direction });
|
90 |
+
};
|
91 |
+
|
92 |
+
|
93 |
console.log(filteredData)
|
94 |
|
95 |
const toggleProviderExpansion = (provider: string) => {
|
|
|
185 |
<Table>
|
186 |
<TableHeader>
|
187 |
<TableRow>
|
188 |
+
<TableHead>
|
189 |
+
<button type="button" onClick={() => requestSort('provider')}>
|
190 |
+
Provider {sortConfig?.key === 'provider' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
|
191 |
+
</button>
|
192 |
+
</TableHead>
|
193 |
+
<TableHead>
|
194 |
+
<button type="button" onClick={() => requestSort('model')}>
|
195 |
+
Model {sortConfig?.key === 'model' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
|
196 |
+
</button>
|
197 |
+
</TableHead>
|
198 |
+
<TableHead>
|
199 |
+
<button type="button" onClick={() => requestSort('inputPrice')}>
|
200 |
+
Input Price (per 1M tokens) {sortConfig?.key === 'inputPrice' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
|
201 |
+
</button>
|
202 |
+
</TableHead>
|
203 |
+
<TableHead>
|
204 |
+
<button type="button" onClick={() => requestSort('outputPrice')}>
|
205 |
+
Output Price (per 1M tokens) {sortConfig?.key === 'outputPrice' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
|
206 |
+
</button>
|
207 |
+
</TableHead>
|
208 |
<TableHead>Total Price</TableHead>
|
209 |
{comparisonModels.map((model) => (
|
210 |
<TableHead key={model} colSpan={2}>
|
|
|
247 |
</TableRow>
|
248 |
</TableHeader>
|
249 |
<TableBody>
|
250 |
+
{sortedData.flatMap((provider) =>
|
251 |
provider.models.map((model) => (
|
252 |
<TableRow key={`${provider.provider}-${model.name}`}>
|
253 |
<TableCell>
|
|
|
273 |
return [
|
274 |
<TableCell
|
275 |
key={`${comparisonModel}-input`}
|
276 |
+
className={`${parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) < 0
|
277 |
+
? 'bg-green-100'
|
278 |
+
: parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) > 0
|
|
|
279 |
? 'bg-red-100'
|
280 |
: ''
|
281 |
+
}`}
|
282 |
>
|
283 |
{`${provider.provider}:${model.name}` === comparisonModel
|
284 |
? '0.00%'
|
|
|
286 |
</TableCell>,
|
287 |
<TableCell
|
288 |
key={`${comparisonModel}-output`}
|
289 |
+
className={`${parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) < 0
|
290 |
+
? 'bg-green-100'
|
291 |
+
: parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) > 0
|
|
|
292 |
? 'bg-red-100'
|
293 |
: ''
|
294 |
+
}`}
|
295 |
>
|
296 |
{`${provider.provider}:${model.name}` === comparisonModel
|
297 |
? '0.00%'
|
|
|
304 |
)}
|
305 |
</TableBody>
|
306 |
</Table>
|
307 |
+
|
308 |
+
|
309 |
+
|
310 |
</CardContent>
|
311 |
</Card>
|
312 |
)
|
src/lib/data.ts
CHANGED
@@ -6,7 +6,7 @@ export const mockData: Provider[] = [
|
|
6 |
uri: 'https://openai.com/api/pricing/',
|
7 |
models: [
|
8 |
{ name: 'GPT-4o', inputPrice: 5.0, outputPrice: 15.0 },
|
9 |
-
{ name: 'GPT-4o-mini', inputPrice: 0.15, outputPrice: 0.
|
10 |
{ name: 'GPT-4 (8K)', inputPrice: 30.0, outputPrice: 60.0 },
|
11 |
{ name: 'GPT-4 Turbo', inputPrice: 10.0, outputPrice: 30.0 },
|
12 |
{ name: 'GPT-3.5-turbo', inputPrice: 0.5, outputPrice: 1.5 },
|
|
|
6 |
uri: 'https://openai.com/api/pricing/',
|
7 |
models: [
|
8 |
{ name: 'GPT-4o', inputPrice: 5.0, outputPrice: 15.0 },
|
9 |
+
{ name: 'GPT-4o-mini', inputPrice: 0.15, outputPrice: 0.60 },
|
10 |
{ name: 'GPT-4 (8K)', inputPrice: 30.0, outputPrice: 60.0 },
|
11 |
{ name: 'GPT-4 Turbo', inputPrice: 10.0, outputPrice: 30.0 },
|
12 |
{ name: 'GPT-3.5-turbo', inputPrice: 0.5, outputPrice: 1.5 },
|