@huggingface/tasks 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/commonjs/index.d.ts +1 -0
  2. package/dist/commonjs/index.d.ts.map +1 -1
  3. package/dist/commonjs/index.js +1 -0
  4. package/dist/commonjs/inference-providers.d.ts +10 -0
  5. package/dist/commonjs/inference-providers.d.ts.map +1 -0
  6. package/dist/commonjs/inference-providers.js +16 -0
  7. package/dist/commonjs/snippets/curl.d.ts +8 -8
  8. package/dist/commonjs/snippets/curl.d.ts.map +1 -1
  9. package/dist/commonjs/snippets/curl.js +58 -30
  10. package/dist/commonjs/snippets/js.d.ts +11 -10
  11. package/dist/commonjs/snippets/js.d.ts.map +1 -1
  12. package/dist/commonjs/snippets/js.js +162 -53
  13. package/dist/commonjs/snippets/python.d.ts +12 -12
  14. package/dist/commonjs/snippets/python.d.ts.map +1 -1
  15. package/dist/commonjs/snippets/python.js +141 -71
  16. package/dist/commonjs/snippets/types.d.ts +1 -1
  17. package/dist/commonjs/snippets/types.d.ts.map +1 -1
  18. package/dist/esm/index.d.ts +1 -0
  19. package/dist/esm/index.d.ts.map +1 -1
  20. package/dist/esm/index.js +1 -0
  21. package/dist/esm/inference-providers.d.ts +10 -0
  22. package/dist/esm/inference-providers.d.ts.map +1 -0
  23. package/dist/esm/inference-providers.js +12 -0
  24. package/dist/esm/snippets/curl.d.ts +8 -8
  25. package/dist/esm/snippets/curl.d.ts.map +1 -1
  26. package/dist/esm/snippets/curl.js +58 -29
  27. package/dist/esm/snippets/js.d.ts +11 -10
  28. package/dist/esm/snippets/js.d.ts.map +1 -1
  29. package/dist/esm/snippets/js.js +159 -50
  30. package/dist/esm/snippets/python.d.ts +12 -12
  31. package/dist/esm/snippets/python.d.ts.map +1 -1
  32. package/dist/esm/snippets/python.js +140 -69
  33. package/dist/esm/snippets/types.d.ts +1 -1
  34. package/dist/esm/snippets/types.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/index.ts +2 -0
  37. package/src/inference-providers.ts +16 -0
  38. package/src/snippets/curl.ts +72 -23
  39. package/src/snippets/js.ts +189 -56
  40. package/src/snippets/python.ts +154 -75
  41. package/src/snippets/types.ts +1 -1
@@ -1,7 +1,45 @@
1
+ import { openAIbaseUrl } from "../inference-providers.js";
1
2
  import { stringifyGenerationConfig, stringifyMessages } from "./common.js";
2
3
  import { getModelInputSnippet } from "./inputs.js";
3
- export const snippetBasic = (model, accessToken) => ({
4
- content: `async function query(data) {
4
+ const HFJS_METHODS = {
5
+ "text-classification": "textClassification",
6
+ "token-classification": "tokenClassification",
7
+ "table-question-answering": "tableQuestionAnswering",
8
+ "question-answering": "questionAnswering",
9
+ translation: "translation",
10
+ summarization: "summarization",
11
+ "feature-extraction": "featureExtraction",
12
+ "text-generation": "textGeneration",
13
+ "text2text-generation": "textGeneration",
14
+ "fill-mask": "fillMask",
15
+ "sentence-similarity": "sentenceSimilarity",
16
+ };
17
+ export const snippetBasic = (model, accessToken, provider) => {
18
+ return [
19
+ ...(model.pipeline_tag && model.pipeline_tag in HFJS_METHODS
20
+ ? [
21
+ {
22
+ client: "huggingface.js",
23
+ content: `\
24
+ import { HfInference } from "@huggingface/inference";
25
+
26
+ const client = new HfInference("${accessToken || `{API_TOKEN}`}");
27
+
28
+ const output = await client.${HFJS_METHODS[model.pipeline_tag]}({
29
+ model: "${model.id}",
30
+ inputs: ${getModelInputSnippet(model)},
31
+ provider: "${provider}",
32
+ });
33
+
34
+ console.log(output)
35
+ `,
36
+ },
37
+ ]
38
+ : []),
39
+ {
40
+ client: "fetch",
41
+ content: `\
42
+ async function query(data) {
5
43
  const response = await fetch(
6
44
  "https://api-inference.huggingface.co/models/${model.id}",
7
45
  {
@@ -20,8 +58,10 @@ export const snippetBasic = (model, accessToken) => ({
20
58
  query({"inputs": ${getModelInputSnippet(model)}}).then((response) => {
21
59
  console.log(JSON.stringify(response));
22
60
  });`,
23
- });
24
- export const snippetTextGeneration = (model, accessToken, opts) => {
61
+ },
62
+ ];
63
+ };
64
+ export const snippetTextGeneration = (model, accessToken, provider, opts) => {
25
65
  if (model.tags.includes("conversational")) {
26
66
  // Conversational model detected, so we display a code snippet that features the Messages API
27
67
  const streaming = opts?.streaming ?? true;
@@ -50,6 +90,7 @@ let out = "";
50
90
  const stream = client.chatCompletionStream({
51
91
  model: "${model.id}",
52
92
  messages: ${messagesStr},
93
+ provider: "${provider}",
53
94
  ${configStr}
54
95
  });
55
96
 
@@ -66,8 +107,8 @@ for await (const chunk of stream) {
66
107
  content: `import { OpenAI } from "openai";
67
108
 
68
109
  const client = new OpenAI({
69
- baseURL: "https://api-inference.huggingface.co/v1/",
70
- apiKey: "${accessToken || `{API_TOKEN}`}"
110
+ baseURL: "${openAIbaseUrl(provider)}",
111
+ apiKey: "${accessToken || `{API_TOKEN}`}"
71
112
  });
72
113
 
73
114
  let out = "";
@@ -100,6 +141,7 @@ const client = new HfInference("${accessToken || `{API_TOKEN}`}");
100
141
  const chatCompletion = await client.chatCompletion({
101
142
  model: "${model.id}",
102
143
  messages: ${messagesStr},
144
+ provider: "${provider}",
103
145
  ${configStr}
104
146
  });
105
147
 
@@ -110,8 +152,8 @@ console.log(chatCompletion.choices[0].message);`,
110
152
  content: `import { OpenAI } from "openai";
111
153
 
112
154
  const client = new OpenAI({
113
- baseURL: "https://api-inference.huggingface.co/v1/",
114
- apiKey: "${accessToken || `{API_TOKEN}`}"
155
+ baseURL: "${openAIbaseUrl(provider)}",
156
+ apiKey: "${accessToken || `{API_TOKEN}`}"
115
157
  });
116
158
 
117
159
  const chatCompletion = await client.chat.completions.create({
@@ -126,32 +168,58 @@ console.log(chatCompletion.choices[0].message);`,
126
168
  }
127
169
  }
128
170
  else {
129
- return snippetBasic(model, accessToken);
171
+ return snippetBasic(model, accessToken, provider);
130
172
  }
131
173
  };
132
- export const snippetZeroShotClassification = (model, accessToken) => ({
133
- content: `async function query(data) {
134
- const response = await fetch(
135
- "https://api-inference.huggingface.co/models/${model.id}",
136
- {
137
- headers: {
138
- Authorization: "Bearer ${accessToken || `{API_TOKEN}`}",
139
- "Content-Type": "application/json",
140
- },
141
- method: "POST",
142
- body: JSON.stringify(data),
174
+ export const snippetZeroShotClassification = (model, accessToken) => {
175
+ return [
176
+ {
177
+ client: "fetch",
178
+ content: `async function query(data) {
179
+ const response = await fetch(
180
+ "https://api-inference.huggingface.co/models/${model.id}",
181
+ {
182
+ headers: {
183
+ Authorization: "Bearer ${accessToken || `{API_TOKEN}`}",
184
+ "Content-Type": "application/json",
185
+ },
186
+ method: "POST",
187
+ body: JSON.stringify(data),
188
+ }
189
+ );
190
+ const result = await response.json();
191
+ return result;
143
192
  }
144
- );
145
- const result = await response.json();
146
- return result;
147
- }
193
+
194
+ query({"inputs": ${getModelInputSnippet(model)}, "parameters": {"candidate_labels": ["refund", "legal", "faq"]}}).then((response) => {
195
+ console.log(JSON.stringify(response));
196
+ });`,
197
+ },
198
+ ];
199
+ };
200
+ export const snippetTextToImage = (model, accessToken, provider) => {
201
+ return [
202
+ {
203
+ client: "huggingface.js",
204
+ content: `\
205
+ import { HfInference } from "@huggingface/inference";
148
206
 
149
- query({"inputs": ${getModelInputSnippet(model)}, "parameters": {"candidate_labels": ["refund", "legal", "faq"]}}).then((response) => {
150
- console.log(JSON.stringify(response));
151
- });`,
207
+ const client = new HfInference("${accessToken || `{API_TOKEN}`}");
208
+
209
+ const image = await client.textToImage({
210
+ model: "${model.id}",
211
+ inputs: ${getModelInputSnippet(model)},
212
+ parameters: { num_inference_steps: 5 },
213
+ provider: "${provider}",
152
214
  });
153
- export const snippetTextToImage = (model, accessToken) => ({
154
- content: `async function query(data) {
215
+ /// Use the generated image (it's a Blob)
216
+ `,
217
+ },
218
+ ...(provider === "hf-inference"
219
+ ? [
220
+ {
221
+ client: "fetch",
222
+ content: `async function query(data) {
155
223
  const response = await fetch(
156
224
  "https://api-inference.huggingface.co/models/${model.id}",
157
225
  {
@@ -169,8 +237,15 @@ export const snippetTextToImage = (model, accessToken) => ({
169
237
  query({"inputs": ${getModelInputSnippet(model)}}).then((response) => {
170
238
  // Use image
171
239
  });`,
172
- });
173
- export const snippetTextToAudio = (model, accessToken) => {
240
+ },
241
+ ]
242
+ : []),
243
+ ];
244
+ };
245
+ export const snippetTextToAudio = (model, accessToken, provider) => {
246
+ if (provider !== "hf-inference") {
247
+ return [];
248
+ }
174
249
  const commonSnippet = `async function query(data) {
175
250
  const response = await fetch(
176
251
  "https://api-inference.huggingface.co/models/${model.id}",
@@ -184,21 +259,26 @@ export const snippetTextToAudio = (model, accessToken) => {
184
259
  }
185
260
  );`;
186
261
  if (model.library_name === "transformers") {
187
- return {
188
- content: commonSnippet +
189
- `
262
+ return [
263
+ {
264
+ client: "fetch",
265
+ content: commonSnippet +
266
+ `
190
267
  const result = await response.blob();
191
268
  return result;
192
269
  }
193
270
  query({"inputs": ${getModelInputSnippet(model)}}).then((response) => {
194
271
  // Returns a byte object of the Audio wavform. Use it directly!
195
272
  });`,
196
- };
273
+ },
274
+ ];
197
275
  }
198
276
  else {
199
- return {
200
- content: commonSnippet +
201
- `
277
+ return [
278
+ {
279
+ client: "fetch",
280
+ content: commonSnippet +
281
+ `
202
282
  const result = await response.json();
203
283
  return result;
204
284
  }
@@ -206,11 +286,41 @@ export const snippetTextToAudio = (model, accessToken) => {
206
286
  query({"inputs": ${getModelInputSnippet(model)}}).then((response) => {
207
287
  console.log(JSON.stringify(response));
208
288
  });`,
209
- };
289
+ },
290
+ ];
210
291
  }
211
292
  };
212
- export const snippetFile = (model, accessToken) => ({
213
- content: `async function query(filename) {
293
+ export const snippetAutomaticSpeechRecognition = (model, accessToken, provider) => {
294
+ return [
295
+ {
296
+ client: "huggingface.js",
297
+ content: `\
298
+ import { HfInference } from "@huggingface/inference";
299
+
300
+ const client = new HfInference("${accessToken || `{API_TOKEN}`}");
301
+
302
+ const data = fs.readFileSync(${getModelInputSnippet(model)});
303
+
304
+ const output = await client.automaticSpeechRecognition({
305
+ data,
306
+ model: "${model.id}",
307
+ provider: "${provider}",
308
+ });
309
+
310
+ console.log(output);
311
+ `,
312
+ },
313
+ ...(provider === "hf-inference" ? snippetFile(model, accessToken, provider) : []),
314
+ ];
315
+ };
316
+ export const snippetFile = (model, accessToken, provider) => {
317
+ if (provider !== "hf-inference") {
318
+ return [];
319
+ }
320
+ return [
321
+ {
322
+ client: "fetch",
323
+ content: `async function query(filename) {
214
324
  const data = fs.readFileSync(filename);
215
325
  const response = await fetch(
216
326
  "https://api-inference.huggingface.co/models/${model.id}",
@@ -230,9 +340,11 @@ export const snippetFile = (model, accessToken) => ({
230
340
  query(${getModelInputSnippet(model)}).then((response) => {
231
341
  console.log(JSON.stringify(response));
232
342
  });`,
233
- });
343
+ },
344
+ ];
345
+ };
234
346
  export const jsSnippets = {
235
- // Same order as in js/src/lib/interfaces/Types.ts
347
+ // Same order as in tasks/src/pipelines.ts
236
348
  "text-classification": snippetBasic,
237
349
  "token-classification": snippetBasic,
238
350
  "table-question-answering": snippetBasic,
@@ -246,7 +358,7 @@ export const jsSnippets = {
246
358
  "text2text-generation": snippetBasic,
247
359
  "fill-mask": snippetBasic,
248
360
  "sentence-similarity": snippetBasic,
249
- "automatic-speech-recognition": snippetFile,
361
+ "automatic-speech-recognition": snippetAutomaticSpeechRecognition,
250
362
  "text-to-image": snippetTextToImage,
251
363
  "text-to-speech": snippetTextToAudio,
252
364
  "text-to-audio": snippetTextToAudio,
@@ -257,11 +369,8 @@ export const jsSnippets = {
257
369
  "object-detection": snippetFile,
258
370
  "image-segmentation": snippetFile,
259
371
  };
260
- export function getJsInferenceSnippet(model, accessToken, opts) {
372
+ export function getJsInferenceSnippet(model, accessToken, provider, opts) {
261
373
  return model.pipeline_tag && model.pipeline_tag in jsSnippets
262
- ? jsSnippets[model.pipeline_tag]?.(model, accessToken, opts) ?? { content: "" }
263
- : { content: "" };
264
- }
265
- export function hasJsInferenceSnippet(model) {
266
- return !!model.pipeline_tag && model.pipeline_tag in jsSnippets;
374
+ ? jsSnippets[model.pipeline_tag]?.(model, accessToken, provider, opts) ?? []
375
+ : [];
267
376
  }
@@ -1,22 +1,22 @@
1
+ import { type InferenceProvider } from "../inference-providers.js";
1
2
  import type { PipelineType } from "../pipelines.js";
2
3
  import type { ChatCompletionInputMessage, GenerationParameters } from "../tasks/index.js";
3
4
  import type { InferenceSnippet, ModelDataMinimal } from "./types.js";
4
- export declare const snippetConversational: (model: ModelDataMinimal, accessToken: string, opts?: {
5
+ export declare const snippetConversational: (model: ModelDataMinimal, accessToken: string, provider: InferenceProvider, opts?: {
5
6
  streaming?: boolean;
6
7
  messages?: ChatCompletionInputMessage[];
7
8
  temperature?: GenerationParameters["temperature"];
8
9
  max_tokens?: GenerationParameters["max_tokens"];
9
10
  top_p?: GenerationParameters["top_p"];
10
11
  }) => InferenceSnippet[];
11
- export declare const snippetZeroShotClassification: (model: ModelDataMinimal) => InferenceSnippet;
12
- export declare const snippetZeroShotImageClassification: (model: ModelDataMinimal) => InferenceSnippet;
13
- export declare const snippetBasic: (model: ModelDataMinimal) => InferenceSnippet;
14
- export declare const snippetFile: (model: ModelDataMinimal) => InferenceSnippet;
15
- export declare const snippetTextToImage: (model: ModelDataMinimal, accessToken: string) => InferenceSnippet[];
16
- export declare const snippetTabular: (model: ModelDataMinimal) => InferenceSnippet;
17
- export declare const snippetTextToAudio: (model: ModelDataMinimal) => InferenceSnippet;
18
- export declare const snippetDocumentQuestionAnswering: (model: ModelDataMinimal) => InferenceSnippet;
19
- export declare const pythonSnippets: Partial<Record<PipelineType, (model: ModelDataMinimal, accessToken: string, opts?: Record<string, unknown>) => InferenceSnippet | InferenceSnippet[]>>;
20
- export declare function getPythonInferenceSnippet(model: ModelDataMinimal, accessToken: string, opts?: Record<string, unknown>): InferenceSnippet | InferenceSnippet[];
21
- export declare function hasPythonInferenceSnippet(model: ModelDataMinimal): boolean;
12
+ export declare const snippetZeroShotClassification: (model: ModelDataMinimal) => InferenceSnippet[];
13
+ export declare const snippetZeroShotImageClassification: (model: ModelDataMinimal) => InferenceSnippet[];
14
+ export declare const snippetBasic: (model: ModelDataMinimal) => InferenceSnippet[];
15
+ export declare const snippetFile: (model: ModelDataMinimal) => InferenceSnippet[];
16
+ export declare const snippetTextToImage: (model: ModelDataMinimal, accessToken: string, provider: InferenceProvider) => InferenceSnippet[];
17
+ export declare const snippetTabular: (model: ModelDataMinimal) => InferenceSnippet[];
18
+ export declare const snippetTextToAudio: (model: ModelDataMinimal) => InferenceSnippet[];
19
+ export declare const snippetDocumentQuestionAnswering: (model: ModelDataMinimal) => InferenceSnippet[];
20
+ export declare const pythonSnippets: Partial<Record<PipelineType, (model: ModelDataMinimal, accessToken: string, provider: InferenceProvider, opts?: Record<string, unknown>) => InferenceSnippet[]>>;
21
+ export declare function getPythonInferenceSnippet(model: ModelDataMinimal, accessToken: string, provider: InferenceProvider, opts?: Record<string, unknown>): InferenceSnippet[];
22
22
  //# sourceMappingURL=python.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/snippets/python.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOrE,eAAO,MAAM,qBAAqB,UAC1B,gBAAgB,eACV,MAAM,SACZ;IACN,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,WAAW,CAAC,EAAE,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;CACtC,KACC,gBAAgB,EAiGlB,CAAC;AAEF,eAAO,MAAM,6BAA6B,UAAW,gBAAgB,KAAG,gBAStE,CAAC;AAEH,eAAO,MAAM,kCAAkC,UAAW,gBAAgB,KAAG,gBAe3E,CAAC;AAEH,eAAO,MAAM,YAAY,UAAW,gBAAgB,KAAG,gBAQrD,CAAC;AAEH,eAAO,MAAM,WAAW,UAAW,gBAAgB,KAAG,gBAQpD,CAAC;AAEH,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,eAAe,MAAM,KAAG,gBAAgB,EAqBjG,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,gBAAgB,KAAG,gBAOvD,CAAC;AAEH,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAAG,gBA+B5D,CAAC;AAEF,eAAO,MAAM,gCAAgC,UAAW,gBAAgB,KAAG,gBAWzE,CAAC;AAEH,eAAO,MAAM,cAAc,EAAE,OAAO,CACnC,MAAM,CACL,YAAY,EACZ,CACC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,gBAAgB,GAAG,gBAAgB,EAAE,CAC1C,CA8BD,CAAC;AAEF,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB,GAAG,gBAAgB,EAAE,CA0BvC;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAE1E"}
1
+ {"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../src/snippets/python.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAWrE,eAAO,MAAM,qBAAqB,UAC1B,gBAAgB,eACV,MAAM,YACT,iBAAiB,SACpB;IACN,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACxC,WAAW,CAAC,EAAE,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;CACtC,KACC,gBAAgB,EA+FlB,CAAC;AAEF,eAAO,MAAM,6BAA6B,UAAW,gBAAgB,KAAG,gBAAgB,EAcvF,CAAC;AAEF,eAAO,MAAM,kCAAkC,UAAW,gBAAgB,KAAG,gBAAgB,EAoB5F,CAAC;AAEF,eAAO,MAAM,YAAY,UAAW,gBAAgB,KAAG,gBAAgB,EAatE,CAAC;AAEF,eAAO,MAAM,WAAW,UAAW,gBAAgB,KAAG,gBAAgB,EAarE,CAAC;AAEF,eAAO,MAAM,kBAAkB,UACvB,gBAAgB,eACV,MAAM,YACT,iBAAiB,KACzB,gBAAgB,EAqDlB,CAAC;AAEF,eAAO,MAAM,cAAc,UAAW,gBAAgB,KAAG,gBAAgB,EAYxE,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAAG,gBAAgB,EAqC5E,CAAC;AAEF,eAAO,MAAM,gCAAgC,UAAW,gBAAgB,KAAG,gBAAgB,EAgB1F,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,OAAO,CACnC,MAAM,CACL,YAAY,EACZ,CACC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,gBAAgB,EAAE,CACvB,CA8BD,CAAC;AAEF,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB,EAAE,CA+BpB"}