:gem: [Feature] Enable request available models with api_key
Browse files- networks/llm_requester.js +7 -1
- storages/endpoint_storage.js +39 -22
networks/llm_requester.js
CHANGED
@@ -133,8 +133,9 @@ export class ChatCompletionsRequester {
|
|
133 |
}
|
134 |
|
135 |
export class AvailableModelsRequester {
|
136 |
-
constructor(openai_endpoint) {
|
137 |
this.openai_endpoint = openai_endpoint;
|
|
|
138 |
this.backend_request_endpoint = "/models";
|
139 |
this.controller = new AbortController();
|
140 |
this.available_models = [];
|
@@ -146,6 +147,11 @@ export class AvailableModelsRequester {
|
|
146 |
this.openai_request_headers = {
|
147 |
"Content-Type": "application/json",
|
148 |
};
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
150 |
construct_backend_request_body() {
|
151 |
this.backend_request_body = {
|
|
|
133 |
}
|
134 |
|
135 |
export class AvailableModelsRequester {
|
136 |
+
constructor(openai_endpoint, openai_api_key = null) {
|
137 |
this.openai_endpoint = openai_endpoint;
|
138 |
+
this.openai_api_key = openai_api_key;
|
139 |
this.backend_request_endpoint = "/models";
|
140 |
this.controller = new AbortController();
|
141 |
this.available_models = [];
|
|
|
147 |
this.openai_request_headers = {
|
148 |
"Content-Type": "application/json",
|
149 |
};
|
150 |
+
if (this.openai_api_key) {
|
151 |
+
this.openai_request_headers[
|
152 |
+
"Authorization"
|
153 |
+
] = `Bearer ${this.openai_api_key}`;
|
154 |
+
}
|
155 |
}
|
156 |
construct_backend_request_body() {
|
157 |
this.backend_request_body = {
|
storages/endpoint_storage.js
CHANGED
@@ -5,7 +5,7 @@ class EndpointStorage {
|
|
5 |
this.init_database();
|
6 |
this.load_local_endpoints().then(() => {
|
7 |
this.create_endpoint_and_api_key_items();
|
8 |
-
this.fill_available_models_select();
|
9 |
});
|
10 |
}
|
11 |
init_database() {
|
@@ -130,7 +130,11 @@ class EndpointStorage {
|
|
130 |
});
|
131 |
console.log(`new_endpoint: ${endpoint_input_value}`);
|
132 |
}
|
133 |
-
this.fill_available_models_select(
|
|
|
|
|
|
|
|
|
134 |
});
|
135 |
|
136 |
let remove_endpoint_buttons = endpoint_and_api_key_item.find(
|
@@ -150,10 +154,11 @@ class EndpointStorage {
|
|
150 |
this.db.endpoints.delete(endpoint_input_value);
|
151 |
// remove models of current endpoint from available_models_select
|
152 |
let available_models_select = $("#available-models-select");
|
153 |
-
let model_value = this.construct_model_name_and_value(
|
154 |
-
endpoint_input_value,
|
155 |
-
""
|
156 |
-
|
|
|
157 |
available_models_select
|
158 |
.find(`option[value^="${model_value}"]`)
|
159 |
.remove();
|
@@ -161,13 +166,14 @@ class EndpointStorage {
|
|
161 |
}
|
162 |
});
|
163 |
}
|
164 |
-
async fetch_available_models(endpoint) {
|
165 |
console.log("fetch available models for endpoint:", endpoint);
|
166 |
// if endpoint not starts with http(s), skip,
|
167 |
// such as "user-customized", which is might be local functions or agents
|
168 |
if (endpoint.startsWith("http")) {
|
169 |
let available_models_requester = new AvailableModelsRequester(
|
170 |
-
endpoint
|
|
|
171 |
);
|
172 |
console.log(`try to fetch available_models from ${endpoint}`);
|
173 |
// update available_models field of endpoint index in db.endpoints
|
@@ -182,21 +188,23 @@ class EndpointStorage {
|
|
182 |
return Promise.resolve([]);
|
183 |
}
|
184 |
}
|
185 |
-
fill_available_models_select(
|
|
|
|
|
|
|
|
|
186 |
// fetch available_models for all endpoints, and then fill available_models_select
|
187 |
let available_models_select = $("#available-models-select");
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
const fill_models = (endpoint) => {
|
192 |
-
return this.fetch_available_models(endpoint).then(
|
193 |
(available_models) => {
|
194 |
available_models.forEach((model_id) => {
|
195 |
let model_name_and_value =
|
196 |
-
this.construct_model_name_and_value(
|
197 |
-
endpoint,
|
198 |
-
model_id
|
199 |
-
|
|
|
200 |
let option = new Option(
|
201 |
model_name_and_value[0],
|
202 |
model_name_and_value[1]
|
@@ -207,12 +215,17 @@ class EndpointStorage {
|
|
207 |
);
|
208 |
};
|
209 |
|
|
|
|
|
|
|
|
|
|
|
210 |
if (endpoint) {
|
211 |
-
promises.push(fill_models(endpoint));
|
212 |
} else {
|
213 |
this.db.endpoints.toArray().then((endpoints) => {
|
214 |
endpoints.map(async (row) => {
|
215 |
-
promises.push(fill_models(row.endpoint));
|
216 |
});
|
217 |
});
|
218 |
}
|
@@ -221,13 +234,17 @@ class EndpointStorage {
|
|
221 |
this.set_default_model();
|
222 |
});
|
223 |
}
|
224 |
-
construct_model_name_and_value(
|
|
|
|
|
|
|
|
|
225 |
let endpoint_hostname = new URL(endpoint).hostname
|
226 |
.split(".")[0]
|
227 |
.split("-")[0];
|
228 |
model_id = model_id.split("/").pop();
|
229 |
let model_name = `${model_id} (${endpoint_hostname})`;
|
230 |
-
let model_value = `${endpoint}|${model_id}`;
|
231 |
return [model_name, model_value];
|
232 |
}
|
233 |
set_default_model() {
|
|
|
5 |
this.init_database();
|
6 |
this.load_local_endpoints().then(() => {
|
7 |
this.create_endpoint_and_api_key_items();
|
8 |
+
this.fill_available_models_select({ clear_select: true });
|
9 |
});
|
10 |
}
|
11 |
init_database() {
|
|
|
130 |
});
|
131 |
console.log(`new_endpoint: ${endpoint_input_value}`);
|
132 |
}
|
133 |
+
this.fill_available_models_select({
|
134 |
+
endpoint: endpoint_input_value,
|
135 |
+
api_key: api_key_input_value,
|
136 |
+
clear_select: false,
|
137 |
+
});
|
138 |
});
|
139 |
|
140 |
let remove_endpoint_buttons = endpoint_and_api_key_item.find(
|
|
|
154 |
this.db.endpoints.delete(endpoint_input_value);
|
155 |
// remove models of current endpoint from available_models_select
|
156 |
let available_models_select = $("#available-models-select");
|
157 |
+
let model_value = this.construct_model_name_and_value({
|
158 |
+
endpoint: endpoint_input_value,
|
159 |
+
model_id: "",
|
160 |
+
api_key: "",
|
161 |
+
})[1];
|
162 |
available_models_select
|
163 |
.find(`option[value^="${model_value}"]`)
|
164 |
.remove();
|
|
|
166 |
}
|
167 |
});
|
168 |
}
|
169 |
+
async fetch_available_models(endpoint, api_key = null) {
|
170 |
console.log("fetch available models for endpoint:", endpoint);
|
171 |
// if endpoint not starts with http(s), skip,
|
172 |
// such as "user-customized", which is might be local functions or agents
|
173 |
if (endpoint.startsWith("http")) {
|
174 |
let available_models_requester = new AvailableModelsRequester(
|
175 |
+
endpoint,
|
176 |
+
api_key
|
177 |
);
|
178 |
console.log(`try to fetch available_models from ${endpoint}`);
|
179 |
// update available_models field of endpoint index in db.endpoints
|
|
|
188 |
return Promise.resolve([]);
|
189 |
}
|
190 |
}
|
191 |
+
fill_available_models_select({
|
192 |
+
endpoint = null,
|
193 |
+
api_key = null,
|
194 |
+
clear_select = false,
|
195 |
+
} = {}) {
|
196 |
// fetch available_models for all endpoints, and then fill available_models_select
|
197 |
let available_models_select = $("#available-models-select");
|
198 |
+
const fill_models = (endpoint, api_key) => {
|
199 |
+
return this.fetch_available_models(endpoint, api_key).then(
|
|
|
|
|
|
|
200 |
(available_models) => {
|
201 |
available_models.forEach((model_id) => {
|
202 |
let model_name_and_value =
|
203 |
+
this.construct_model_name_and_value({
|
204 |
+
endpoint: endpoint,
|
205 |
+
model_id: model_id,
|
206 |
+
api_key: api_key,
|
207 |
+
});
|
208 |
let option = new Option(
|
209 |
model_name_and_value[0],
|
210 |
model_name_and_value[1]
|
|
|
215 |
);
|
216 |
};
|
217 |
|
218 |
+
if (clear_select) {
|
219 |
+
available_models_select.empty();
|
220 |
+
}
|
221 |
+
|
222 |
+
let promises = [];
|
223 |
if (endpoint) {
|
224 |
+
promises.push(fill_models(endpoint, api_key));
|
225 |
} else {
|
226 |
this.db.endpoints.toArray().then((endpoints) => {
|
227 |
endpoints.map(async (row) => {
|
228 |
+
promises.push(fill_models(row.endpoint, row.api_key));
|
229 |
});
|
230 |
});
|
231 |
}
|
|
|
234 |
this.set_default_model();
|
235 |
});
|
236 |
}
|
237 |
+
construct_model_name_and_value({
|
238 |
+
endpoint,
|
239 |
+
model_id,
|
240 |
+
api_key = null,
|
241 |
+
} = {}) {
|
242 |
let endpoint_hostname = new URL(endpoint).hostname
|
243 |
.split(".")[0]
|
244 |
.split("-")[0];
|
245 |
model_id = model_id.split("/").pop();
|
246 |
let model_name = `${model_id} (${endpoint_hostname})`;
|
247 |
+
let model_value = `${endpoint}|${model_id}|${api_key}`;
|
248 |
return [model_name, model_value];
|
249 |
}
|
250 |
set_default_model() {
|