Skip to content

Commit fe2803e

Browse files
authored
fix: migrate JSON catalogs to Typesript (#3475)
* fix: migrate JSON catalogs to Typesript Signed-off-by: Simon Rey <[email protected]> * fix: migrate JSON catalogs to Typesript Signed-off-by: Simon Rey <[email protected]> --------- Signed-off-by: Simon Rey <[email protected]>
1 parent edb858b commit fe2803e

File tree

11 files changed

+807
-768
lines changed

11 files changed

+807
-768
lines changed

eslint.config.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@ export default [
164164
*/
165165
'comma-dangle': ['warn', 'always-multiline'],
166166
/**
167-
* Just for beauty
167+
* Let prettier handle the quotes cause I had conflicts
168168
*/
169-
quotes: ['error', 'single', { allowTemplateLiterals: true }],
169+
quotes: "off",
170170

171171
// disabled import/namespace rule as the plug-in is not fully compatible using the compat mode
172172
'import/namespace': 'off',

packages/backend/src/assets/ai.json

Lines changed: 0 additions & 590 deletions
This file was deleted.

packages/backend/src/assets/ai.ts

Lines changed: 633 additions & 0 deletions
Large diffs are not rendered by default.

packages/backend/src/managers/catalogManager.spec.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,21 @@
1919
/* eslint-disable @typescript-eslint/no-explicit-any */
2020

2121
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
22-
import content from '../tests/ai-test.json';
23-
import userContent from '../tests/ai-user-test.json';
2422
import { EventEmitter, window } from '@podman-desktop/api';
2523
import { CatalogManager } from './catalogManager';
2624

2725
import type { Stats } from 'node:fs';
2826
import { promises, existsSync } from 'node:fs';
2927
import type { ApplicationCatalog } from '@shared/models/IApplicationCatalog';
3028
import path from 'node:path';
31-
import { version } from '../assets/ai.json';
3229
import * as catalogUtils from '../utils/catalogUtils';
3330
import type { RpcExtension } from '@shared/messages/MessageProxy';
31+
import { testCatalog } from '../tests/ai-test';
32+
import { defaultCatalog } from '../assets/ai';
33+
import { userTestCatalog } from '../tests/ai-user-test';
3434

35-
vi.mock('../assets/ai.json', async importOriginal => {
36-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
37-
const { version } = await importOriginal<typeof import('../assets/ai.json')>();
38-
return {
39-
default: { ...content, version: version },
40-
version: version,
41-
};
42-
});
35+
const content = testCatalog;
36+
const userContent = userTestCatalog;
4337

4438
vi.mock('node:fs');
4539
vi.mock('node:fs/promises');
@@ -90,6 +84,7 @@ beforeEach(async () => {
9084
fire: vi.fn().mockResolvedValue(true),
9185
} as unknown as RpcExtension,
9286
appUserDirectory,
87+
testCatalog,
9388
);
9489
});
9590

@@ -254,7 +249,7 @@ test('catalog should use user items in favour of default', async () => {
254249
});
255250

256251
test('default catalog should have latest version', () => {
257-
expect(version).toBe(catalogUtils.CatalogFormat.CURRENT);
252+
expect(defaultCatalog.version).toBe(catalogUtils.CatalogFormat.CURRENT);
258253
});
259254

260255
test('wrong catalog version should create a notification', () => {

packages/backend/src/managers/catalogManager.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import type { ApplicationCatalog } from '@shared/models/IApplicationCatalog';
2020
import fs, { promises } from 'node:fs';
2121
import path from 'node:path';
2222
import crypto from 'node:crypto';
23-
import defaultCatalog from '../assets/ai.json';
2423
import type { Recipe } from '@shared/models/IRecipe';
2524
import type { ModelInfo } from '@shared/models/IModelInfo';
2625
import { MSG_NEW_CATALOG_STATE } from '@shared/Messages';
@@ -40,12 +39,14 @@ export class CatalogManager extends Publisher<ApplicationCatalog> implements Dis
4039
readonly onUpdate: Event<ApplicationCatalog> = this._onUpdate.event;
4140

4241
private catalog: ApplicationCatalog;
42+
private defaultCatalog: ApplicationCatalog;
4343
#jsonWatcher: JsonWatcher<ApplicationCatalog> | undefined;
4444
#notification: Disposable | undefined;
4545

4646
constructor(
4747
rpcExtension: RpcExtension,
4848
private appUserDirectory: string,
49+
defaultCatalog: ApplicationCatalog,
4950
) {
5051
super(rpcExtension, MSG_NEW_CATALOG_STATE, () => this.getCatalog());
5152
// We start with an empty catalog, for the methods to work before the catalog is loaded
@@ -55,6 +56,7 @@ export class CatalogManager extends Publisher<ApplicationCatalog> implements Dis
5556
models: [],
5657
recipes: [],
5758
};
59+
this.defaultCatalog = defaultCatalog;
5860
}
5961

6062
/**
@@ -78,7 +80,7 @@ export class CatalogManager extends Publisher<ApplicationCatalog> implements Dis
7880
}
7981

8082
private loadDefaultCatalog(): void {
81-
this.catalog = defaultCatalog as ApplicationCatalog;
83+
this.catalog = this.defaultCatalog;
8284
this.notify();
8385
}
8486

@@ -128,7 +130,7 @@ export class CatalogManager extends Publisher<ApplicationCatalog> implements Dis
128130

129131
// merging default catalog with user catalog
130132
try {
131-
this.catalog = merge(sanitize(defaultCatalog), sanitize({ ...content, version: userCatalogFormat }));
133+
this.catalog = merge(sanitize(this.defaultCatalog), sanitize({ ...content, version: userCatalogFormat }));
132134

133135
// reset notification if everything went smoothly
134136
this.#notification?.dispose();

packages/backend/src/studio-api-impl.spec.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
/* eslint-disable @typescript-eslint/no-explicit-any */
2020

2121
import { beforeEach, expect, test, vi, describe } from 'vitest';
22-
import content from './tests/ai-test.json';
2322
import type { ApplicationManager } from './managers/application/applicationManager';
2423
import { StudioApiImpl } from './studio-api-impl';
2524
import type { InferenceManager } from './managers/inference/inferenceManager';
@@ -43,12 +42,7 @@ import type { RecipeManager } from './managers/recipes/RecipeManager';
4342
import type { PodmanConnection } from './managers/podmanConnection';
4443
import type { NavigationRegistry } from './registries/NavigationRegistry';
4544
import type { RpcExtension } from '@shared/messages/MessageProxy';
46-
47-
vi.mock('./ai.json', () => {
48-
return {
49-
default: content,
50-
};
51-
});
45+
import { testCatalog } from './tests/ai-test';
5246

5347
vi.mock('node:fs', () => {
5448
return {
@@ -119,6 +113,7 @@ beforeEach(async () => {
119113
fire: vi.fn().mockResolvedValue(true),
120114
} as unknown as RpcExtension,
121115
appUserDirectory,
116+
testCatalog,
122117
);
123118

124119
applicationManager = {

packages/backend/src/studio.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ import { LlamaStackManager } from './managers/llama-stack/llamaStackManager';
6565
import { OpenVINO } from './workers/provider/OpenVINO';
6666
import { McpServerManager } from './managers/playground/McpServerManager';
6767
import os from 'node:os';
68+
import { defaultCatalog } from './assets/ai';
6869

6970
export class Studio {
7071
readonly #extensionContext: ExtensionContext;
@@ -211,7 +212,7 @@ export class Studio {
211212
/**
212213
* Create catalog manager, responsible for loading the catalog files and watching for changes
213214
*/
214-
this.#catalogManager = new CatalogManager(this.#rpcExtension, appUserDirectory);
215+
this.#catalogManager = new CatalogManager(this.#rpcExtension, appUserDirectory, defaultCatalog);
215216
await this.#catalogManager.init();
216217

217218
/**

packages/backend/src/tests/ai-test.json

Lines changed: 0 additions & 105 deletions
This file was deleted.

packages/backend/src/tests/ai-test.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import type { ApplicationCatalog } from '@shared/models/IApplicationCatalog';
2+
3+
export const testCatalog: ApplicationCatalog = {
4+
version: '1.0',
5+
recipes: [
6+
{
7+
id: 'chatbot',
8+
description: 'Chat bot application',
9+
name: 'ChatBot',
10+
repository: 'https://github.com/axel7083/locallm',
11+
icon: 'natural-language-processing',
12+
categories: ['natural-language-processing'],
13+
basedir: 'chatbot',
14+
readme:
15+
'# Locallm\n\nThis repo contains artifacts that can be used to build and run LLM (Large Language Model) services locally on your Mac using podman. These containerized LLM services can be used to help developers quickly prototype new LLM based applications, without the need for relying on any other externally hosted services. Since they are already containerized, it also helps developers move from their prototype to production quicker. \n\n## Current Locallm Services: \n\n* [Chatbot](#chatbot)\n* [Text Summarization](#text-summarization)\n* [Fine-tuning](#fine-tuning)\n\n### Chatbot\n\nA simple chatbot using the gradio UI. Learn how to build and run this model service here: [Chatbot](/chatbot/).\n\n### Text Summarization\n\nAn LLM app that can summarize arbitrarily long text inputs. Learn how to build and run this model service here: [Text Summarization](/summarizer/).\n\n### Fine Tuning \n\nThis application allows a user to select a model and a data set they\'d like to fine-tune that model on. Once the application finishes, it outputs a new fine-tuned model for the user to apply to other LLM services. Learn how to build and run this model training job here: [Fine-tuning](/finetune/).\n\n## Architecture\n![](https://raw.githubusercontent.com/MichaelClifford/locallm/main/assets/arch.jpg)\n\nThe diagram above indicates the general architecture for each of the individual model services contained in this repo. The core code available here is the "LLM Task Service" and the "API Server", bundled together under `model_services`. With an appropriately chosen model downloaded onto your host, `model_services/builds` contains the Containerfiles required to build an ARM or an x86 (with CUDA) image depending on your need. These model services are intended to be light-weight and run with smaller hardware footprints (given the Locallm name), but they can be run on any hardware that supports containers and scaled up if needed.\n\nWe also provide demo "AI Applications" under `ai_applications` for each model service to provide an example of how a developers could interact with the model service for their own needs. ',
16+
recommended: ['llama-2-7b-chat.Q5_K_S', 'albedobase-xl-1.3', 'sdxl-turbo'],
17+
},
18+
{
19+
id: 'recipe0',
20+
name: 'Recipe 1',
21+
categories: [],
22+
description: '',
23+
repository: '',
24+
readme: '',
25+
},
26+
{
27+
id: 'recipe1',
28+
name: 'Recipe 1',
29+
categories: [],
30+
description: '',
31+
repository: '',
32+
readme: '',
33+
backend: 'tool1',
34+
languages: ['lang1', 'lang10'],
35+
frameworks: ['fw1', 'fw10'],
36+
},
37+
{
38+
id: 'recipe2',
39+
name: 'Recipe 2',
40+
categories: [],
41+
description: '',
42+
repository: '',
43+
readme: '',
44+
backend: 'tool2',
45+
languages: ['lang2', 'lang10'],
46+
frameworks: ['fw2', 'fw10'],
47+
},
48+
{
49+
id: 'recipe3',
50+
name: 'Recipe 3',
51+
categories: [],
52+
description: '',
53+
repository: '',
54+
readme: '',
55+
backend: 'tool3',
56+
languages: ['lang3', 'lang11'],
57+
frameworks: ['fw2', 'fw10', 'fw11'],
58+
},
59+
],
60+
models: [
61+
{
62+
id: 'llama-2-7b-chat.Q5_K_S',
63+
name: 'Llama-2-7B-Chat-GGUF',
64+
description:
65+
'Llama 2 is a family of state-of-the-art open-access large language models released by Meta today, and we’re excited to fully support the launch with comprehensive integration in Hugging Face. Llama 2 is being released with a very permissive community license and is available for commercial use. The code, pretrained models, and fine-tuned models are all being released today 🔥',
66+
registry: 'Hugging Face',
67+
license: '?',
68+
url: 'https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_S.gguf',
69+
},
70+
{
71+
id: 'albedobase-xl-1.3',
72+
name: 'AlbedoBase XL 1.3',
73+
description:
74+
'Stable Diffusion XL has 6.6 billion parameters, which is about 6.6 times more than the SD v1.5 version. I believe that this is not just a number, but a number that can lead to a significant improvement in performance. It has been a while since we realized that the overall performance of SD v1.5 has improved beyond imagination thanks to the explosive contributions of our community. Therefore, I am working on completing this AlbedoBase XL model in order to optimally reproduce the performance improvement that occurred in v1.5 in this XL version as well. My goal is to directly test the performance of all Checkpoints and LoRAs that are publicly uploaded to Civitai, and merge only the resources that are judged to be optimal after passing through several filters. This will surpass the performance of image-generating AI of companies such as Midjourney. As of now, AlbedoBase XL v0.4 has merged exactly 55 selected checkpoints and 138 LoRAs.',
75+
registry: 'Civital',
76+
license: 'openrail++',
77+
url: '',
78+
},
79+
{
80+
id: 'sdxl-turbo',
81+
name: 'SDXL Turbo',
82+
description:
83+
'SDXL Turbo achieves state-of-the-art performance with a new distillation technology, enabling single-step image generation with unprecedented quality, reducing the required step count from 50 to just one.',
84+
registry: 'Hugging Face',
85+
license: 'sai-c-community',
86+
url: '',
87+
},
88+
],
89+
categories: [
90+
{
91+
id: 'natural-language-processing',
92+
name: 'Natural Language Processing',
93+
description: 'Models that work with text: classify, summarize, translate, or generate text.',
94+
},
95+
{
96+
id: 'computer-vision',
97+
description: 'Process images, from classification to object detection and segmentation.',
98+
name: 'Computer Vision',
99+
},
100+
{
101+
id: 'audio',
102+
description: 'Recognize speech or classify audio with audio models.',
103+
name: 'Audio',
104+
},
105+
{
106+
id: 'multimodal',
107+
description: 'Stuff about multimodal models goes here omg yes amazing.',
108+
name: 'Multimodal',
109+
},
110+
],
111+
};

0 commit comments

Comments
 (0)