CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/util/db-schema/purchase-quotas.ts
Views: 687
1
import { CREATED_BY, ID } from "./crm";
2
import { SCHEMA as schema } from "./index";
3
import { LLM_USERNAMES } from "./llm-utils";
4
import type { Service } from "./purchases";
5
import { Table } from "./types";
6
7
export type { Service };
8
9
// Users will set their spend limits for these broad categories.
10
// TODO: right now there is a separate limit for each quota spec,
11
// which has got ridiculous.
12
const SERVICE_CATEGORIES = ["money", "compute", "license", "ai"];
13
type ServiceCategory = (typeof SERVICE_CATEGORIES)[number];
14
15
interface Spec {
16
display: string; // what to show user to describe this service
17
noSet?: boolean; // if true, then no spend limits are set for this.
18
color: string;
19
category: ServiceCategory;
20
}
21
22
export type QuotaSpec = Record<Service, Spec>;
23
24
const GPT_TURBO_128k: Spec = {
25
display: "OpenAI GPT-4 Turbo 128k",
26
color: "#10a37f",
27
category: "ai",
28
} as const;
29
30
const GPT_TURBO_8K: Spec = {
31
...GPT_TURBO_128k,
32
display: "OpenAI GPT-4 Turbo",
33
} as const;
34
35
const GPT_OMNI_128k: Spec = {
36
display: "OpenAI GPT-4o 128k",
37
color: "#10a37f",
38
category: "ai",
39
} as const;
40
41
const GPT_OMNI_8K: Spec = {
42
...GPT_OMNI_128k,
43
display: "OpenAI GPT-4o",
44
} as const;
45
46
const GPT_OMNI_MINI_128k: Spec = {
47
...GPT_OMNI_128k,
48
display: "OpenAI GPT-4o Mini 128k",
49
};
50
51
const GPT_OMNI_MINI_8K: Spec = {
52
...GPT_OMNI_MINI_128k,
53
display: "OpenAI GPT-4o Mini",
54
};
55
56
const GOOGLE_AI_COLOR = "#ff4d4f";
57
58
// NOTE: all-quotas-config.tsx will automatically filter out those, which are free or not selectable by the user
59
export const QUOTA_SPEC: QuotaSpec = {
60
credit: { display: "Credit", noSet: true, color: "green", category: "money" },
61
refund: { display: "Refund", noSet: true, color: "red", category: "money" },
62
"project-upgrade": {
63
display: "Project Upgrade",
64
color: "#5bc0de",
65
category: "compute",
66
},
67
"compute-server": {
68
display: "Compute Server",
69
color: "#2196f3",
70
category: "compute",
71
},
72
"compute-server-network-usage": {
73
display: "Network Data",
74
color: "#2196f3",
75
category: "compute",
76
},
77
"compute-server-storage": {
78
display: "Cloud Storage",
79
color: "#fbbd05",
80
category: "compute",
81
},
82
license: {
83
display: "License",
84
color: "cyan",
85
noSet: true,
86
category: "license",
87
},
88
"edit-license": {
89
display: "Edit License",
90
color: "gold",
91
noSet: true,
92
category: "license",
93
},
94
voucher: {
95
display: "Voucher",
96
color: "#00238b",
97
noSet: true,
98
category: "money",
99
},
100
// ATTN: LLMs comes below this line, the quotas above are the important ones to show first!
101
"openai-gpt-4": { display: "OpenAI GPT-4", color: "#10a37f", category: "ai" },
102
"openai-gpt-3.5-turbo": {
103
display: "OpenAI GPT-3.5",
104
color: "#10a37f",
105
category: "ai",
106
},
107
"openai-gpt-3.5-turbo-16k": {
108
display: "OpenAI GPT-3.5 16k",
109
color: "#10a37f",
110
category: "ai",
111
},
112
"openai-text-embedding-ada-002": {
113
display: "OpenAI Text Embedding Ada 002",
114
color: "#10a37f",
115
noSet: true, // because this model is not user visible yet
116
category: "ai",
117
},
118
"openai-gpt-4-32k": {
119
display: "OpenAI GPT-4 32k",
120
color: "#10a37f",
121
category: "ai",
122
},
123
"openai-gpt-4-turbo-preview": GPT_TURBO_128k, // the "preview" is over
124
"openai-gpt-4-turbo-preview-8k": GPT_TURBO_8K, // the "preview" is over
125
"openai-gpt-4-turbo": GPT_TURBO_128k,
126
"openai-gpt-4-turbo-8k": GPT_TURBO_8K,
127
"openai-gpt-4o": GPT_OMNI_128k,
128
"openai-gpt-4o-8k": GPT_OMNI_8K,
129
"openai-gpt-4o-mini": GPT_OMNI_MINI_128k,
130
"openai-gpt-4o-mini-8k": GPT_OMNI_MINI_8K,
131
"google-text-bison-001": {
132
display: "Google Palm 2 (Text)",
133
color: GOOGLE_AI_COLOR,
134
noSet: true, // deprecated, will be removed
135
category: "ai",
136
},
137
"google-chat-bison-001": {
138
display: "Google Palm 2 (Chat)",
139
color: GOOGLE_AI_COLOR,
140
noSet: true, // deprecated, will be removed
141
category: "ai",
142
},
143
"google-embedding-gecko-001": {
144
display: "Google Gecko (Embedding)",
145
color: GOOGLE_AI_COLOR,
146
noSet: true, // deprecated, will be removed
147
category: "ai",
148
},
149
"google-gemini-1.5-flash-8k": {
150
display: "Google Gemini 1.5 Flash",
151
color: GOOGLE_AI_COLOR,
152
category: "ai",
153
},
154
"google-gemini-pro": {
155
display: "Google Gemini 1.0 Pro",
156
color: GOOGLE_AI_COLOR,
157
category: "ai",
158
},
159
"google-gemini-1.0-ultra": {
160
display: "Google Gemini 1.0 Ultra",
161
color: GOOGLE_AI_COLOR,
162
category: "ai",
163
},
164
"google-gemini-1.5-pro-8k": {
165
display: LLM_USERNAMES["gemini-1.5-pro-8k"],
166
color: GOOGLE_AI_COLOR,
167
category: "ai",
168
},
169
"google-gemini-1.5-pro": {
170
display: LLM_USERNAMES["gemini-1.5-pro"],
171
color: GOOGLE_AI_COLOR,
172
category: "ai",
173
},
174
"anthropic-claude-3-opus": {
175
display: LLM_USERNAMES["claude-3-opus"],
176
color: "#181818",
177
category: "ai",
178
},
179
"anthropic-claude-3-opus-8k": {
180
display: LLM_USERNAMES["claude-3-opus-8k"],
181
color: "#181818",
182
category: "ai",
183
},
184
"anthropic-claude-3-sonnet": {
185
display: LLM_USERNAMES["claude-3-sonnet"],
186
color: "#181818",
187
category: "ai",
188
},
189
"anthropic-claude-3-sonnet-4k": {
190
display: LLM_USERNAMES["claude-3-sonnet-4k"],
191
color: "#181818",
192
category: "ai",
193
},
194
"anthropic-claude-3-5-sonnet": {
195
display: LLM_USERNAMES["claude-3-5-sonnet"],
196
color: "#181818",
197
category: "ai",
198
},
199
"anthropic-claude-3-5-sonnet-4k": {
200
display: LLM_USERNAMES["claude-3-5-sonnet-4k"],
201
color: "#181818",
202
category: "ai",
203
},
204
"anthropic-claude-3-haiku": {
205
display: LLM_USERNAMES["claude-3-haiku"],
206
color: "#181818",
207
category: "ai",
208
},
209
"anthropic-claude-3-haiku-8k": {
210
display: LLM_USERNAMES["claude-3-haiku-8k"],
211
color: "#181818",
212
category: "ai",
213
},
214
"mistralai-mistral-small-latest": {
215
display: LLM_USERNAMES["mistral-small-latest"],
216
color: "#ff7000", // the orange from their website
217
category: "ai",
218
},
219
"mistralai-mistral-medium-latest": {
220
display: LLM_USERNAMES["mistral-medium-latest"],
221
color: "#ff7000", // the orange from their website
222
category: "ai",
223
},
224
"mistralai-mistral-large-latest": {
225
display: LLM_USERNAMES["mistral-large-latest"],
226
color: "#ff7000", // the orange from their website
227
category: "ai",
228
},
229
} as const;
230
231
// For pay-as-you-go project quota upgrades
232
export interface ProjectQuota {
233
cost?: number; // dollars per hour
234
enabled?: number;
235
cores?: number;
236
disk_quota?: number;
237
memory?: number;
238
mintime?: number;
239
network?: number;
240
member_host?: number;
241
always_running?: number;
242
}
243
244
export const PROJECT_QUOTA_KEYS = new Set<string>([
245
"enabled",
246
"cost",
247
"cores",
248
"disk_quota",
249
"memory",
250
"mintime",
251
"network",
252
"member_host",
253
"always_running",
254
]);
255
256
export function serviceToDisplay(service: Service): string {
257
return QUOTA_SPEC[service]?.display ?? service;
258
}
259
260
Table({
261
name: "purchase_quotas",
262
fields: {
263
id: ID,
264
account_id: CREATED_BY,
265
service: {
266
title: "Service Category",
267
desc: "The service being charged for, e.g., openai-gpt-4, project-upgrade, etc.",
268
type: "string",
269
pg_type: "varchar(127)",
270
},
271
value: {
272
title: "Value",
273
desc: "The maximum amount that user can be charged for this service during one month billing period, in US dollars.",
274
type: "number", // actually comes back as string in queries.
275
pg_type: "REAL",
276
},
277
},
278
rules: {
279
desc: "Purchase Quotas",
280
primary_key: "id",
281
// make it fast to find all quotas for a given account
282
pg_indexes: ["account_id"],
283
// enforce that there is only one quota for each service for a given account
284
pg_unique_indexes: ["(account_id,service)"],
285
user_query: {
286
// set happens though v2 api only to enforce global quota
287
get: {
288
pg_where: [{ "account_id = $::UUID": "account_id" }],
289
fields: {
290
id: null,
291
account_id: null,
292
service: null,
293
value: null,
294
},
295
},
296
},
297
},
298
});
299
300
Table({
301
name: "crm_purchase_quotas",
302
rules: {
303
virtual: "purchase_quotas",
304
primary_key: "id",
305
user_query: {
306
get: {
307
pg_where: [],
308
admin: true,
309
fields: {
310
id: null,
311
account_id: null,
312
service: null,
313
value: null,
314
},
315
},
316
set: {
317
admin: true,
318
fields: {
319
id: true,
320
account_id: true,
321
service: true,
322
value: true,
323
},
324
},
325
},
326
},
327
fields: schema.purchase_quotas.fields,
328
});
329
330