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/llm-utils.test.ts
Views: 687
1
import {
2
DEFAULT_LLM_PRIORITY,
3
DEFAULT_MODEL,
4
getValidLanguageModelName,
5
isCoreLanguageModel,
6
isFreeModel,
7
LANGUAGE_MODEL_SERVICES,
8
LANGUAGE_MODELS,
9
LanguageService,
10
LLM_COST,
11
LLMServicesAvailable,
12
model2vendor,
13
OLLAMA_PREFIX,
14
SERVICES,
15
USER_SELECTABLE_LANGUAGE_MODELS,
16
USER_SELECTABLE_LLMS_BY_VENDOR,
17
} from "./llm-utils";
18
19
describe("llm", () => {
20
const is_cocalc_com = true; // otherwise, the test makes no sense
21
22
test("isFreeModel", () => {
23
expect(isFreeModel("gpt-3", is_cocalc_com)).toBe(true);
24
expect(isFreeModel("gpt-4", is_cocalc_com)).toBe(false);
25
// WARNING: if the following breaks, and ollama becomes non-free, then a couple of assumptions are broken as well.
26
// search for model2service(...) as LanguageService in the codebase!
27
expect(isFreeModel(`${OLLAMA_PREFIX}-1`, is_cocalc_com)).toBe(true);
28
});
29
30
test.each(Object.keys(LLM_COST))(
31
"is valid model names in LLM_COST: '%s'",
32
(model) => {
33
expect(LANGUAGE_MODELS.includes(model as any)).toBe(true);
34
},
35
);
36
37
test("all user selectable ones are valid", () => {
38
for (const model of USER_SELECTABLE_LANGUAGE_MODELS) {
39
expect(LANGUAGE_MODELS.includes(model)).toBe(true);
40
}
41
});
42
43
// none of the user selectable models start with any of the vendor prefixes
44
test.each(USER_SELECTABLE_LANGUAGE_MODELS)(
45
"model '%s' does not start with any vendor prefix",
46
(model) => {
47
for (const prefix of LANGUAGE_MODEL_SERVICES) {
48
expect(model.startsWith(prefix)).toBe(false);
49
}
50
},
51
);
52
53
test.each(LANGUAGE_MODELS)(
54
`check that model2vendor('%s') knows the model`,
55
(model) => {
56
const vendor = model2vendor(model);
57
expect(LANGUAGE_MODEL_SERVICES.includes(vendor.name)).toBe(true);
58
},
59
);
60
61
test(`check model by vendor`, () => {
62
for (const vendor in USER_SELECTABLE_LLMS_BY_VENDOR) {
63
const models = USER_SELECTABLE_LLMS_BY_VENDOR[vendor];
64
for (const model of models) {
65
const v = model2vendor(model);
66
expect(v.name).toBe(vendor);
67
expect(v.url).toContain("https://");
68
}
69
}
70
});
71
72
test("just checking the price", () => {
73
expect(1_000_000 * LLM_COST["gpt-4"].prompt_tokens).toBeCloseTo(30);
74
expect(1_000_000 * LLM_COST["gpt-4"].completion_tokens).toBeCloseTo(60);
75
expect(1_000_000 * LLM_COST["claude-3-opus"].prompt_tokens).toBeCloseTo(15);
76
expect(1_000_000 * LLM_COST["claude-3-opus"].completion_tokens).toBeCloseTo(
77
75,
78
);
79
});
80
81
test("priority list is a shuffle of all llm vendors", () => {
82
// except for "user"
83
const prio = DEFAULT_LLM_PRIORITY;
84
const vend = SERVICES;
85
// test, that those lists have the same elements
86
expect(prio.length).toBe(vend.length);
87
for (const v of vend) {
88
expect(prio.includes(v)).toBe(true);
89
}
90
});
91
92
test("getting valid language model", () => {
93
const selectable_llms = [...USER_SELECTABLE_LANGUAGE_MODELS];
94
const notAvailable = selectable_llms.pop();
95
96
function getModel(model: LanguageService, disabled?: LanguageService) {
97
const allEnabled = LANGUAGE_MODEL_SERVICES.reduce((acc, svc) => {
98
acc[svc] = disabled !== svc;
99
return acc;
100
}, {}) as LLMServicesAvailable;
101
return getValidLanguageModelName({
102
model,
103
filter: allEnabled,
104
ollama: ["phi3"],
105
custom_openai: ["bar"],
106
selectable_llms,
107
});
108
}
109
110
// meaningless name
111
expect(getModel("foobar")).toEqual(DEFAULT_MODEL);
112
expect(getModel("baz-delta99")).toEqual(DEFAULT_MODEL);
113
// gpt 3.5 is disabled
114
expect(getModel("gpt-3.5-turbo")).toEqual(DEFAULT_MODEL);
115
// not available
116
expect(
117
typeof notAvailable === "string" && isCoreLanguageModel(notAvailable),
118
).toBe(true);
119
if (typeof notAvailable === "string") {
120
expect(getModel(notAvailable)).toEqual(DEFAULT_MODEL);
121
}
122
// not disabled
123
expect(getModel("mistral-large-latest")).toEqual("mistral-large-latest");
124
expect(getModel("gpt-4")).toEqual("gpt-4");
125
expect(getModel(DEFAULT_MODEL)).toEqual(DEFAULT_MODEL);
126
expect(getModel("mistral-medium-latest")).toEqual(DEFAULT_MODEL);
127
expect(getModel("mistral-large-latest")).toEqual("mistral-large-latest");
128
expect(getModel("claude-3-haiku-8k")).toEqual("claude-3-haiku-8k");
129
// anthropic service disabled
130
expect(getModel("claude-3-haiku-8k", "anthropic")).toEqual(DEFAULT_MODEL);
131
// ollama
132
expect(getModel("ollama-foo")).toEqual(DEFAULT_MODEL);
133
expect(getModel("ollama-phi3")).toEqual("ollama-phi3");
134
// openai api
135
expect(getModel("custom_openai-foo")).toEqual(DEFAULT_MODEL);
136
expect(getModel("custom_openai-bar")).toEqual("custom_openai-bar");
137
// user models: there are no further checks
138
expect(getModel("user-custom_openai-foo")).toEqual(
139
"user-custom_openai-foo",
140
);
141
expect(getModel("user-openai-gpt-3.5-turbo")).toEqual(
142
"user-openai-gpt-3.5-turbo",
143
);
144
// it's ok to use a model if disabled by the admin, since it's their key
145
expect(getModel("user-anthropic-claude-3-haiku-8k", "anthropic")).toEqual(
146
"user-anthropic-claude-3-haiku-8k",
147
);
148
// meaningless user service
149
expect(getModel("user-baz-delta99")).toEqual(DEFAULT_MODEL);
150
});
151
});
152
153