Skip to content

Commit

Permalink
fix: populate engines, models and legacy settings
Browse files Browse the repository at this point in the history
  • Loading branch information
louis-jan committed Jan 5, 2025
1 parent 6eaca79 commit e25f6ef
Show file tree
Hide file tree
Showing 107 changed files with 736 additions and 3,681 deletions.
17 changes: 15 additions & 2 deletions core/src/browser/extensions/enginesManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,18 @@ export abstract class EngineManagementExtension extends BaseExtension {
* @param name - Inference engine name.
* @returns A Promise that resolves to intall of engine.
*/
abstract installEngine(name: string, engineConfig: EngineConfig): Promise<{ messages: string }>
abstract installEngine(
name: string,
engineConfig: EngineConfig
): Promise<{ messages: string }>

/**
* Add a new remote engine
* @returns A Promise that resolves to intall of engine.
*/
abstract addRemoteEngine(
engineConfig: EngineConfig
): Promise<{ messages: string }>

/**
* @param name - Inference engine name.
Expand All @@ -70,7 +81,9 @@ export abstract class EngineManagementExtension extends BaseExtension {
* @param name - Inference engine name.
* @returns A Promise that resolves to an object of default engine.
*/
abstract getDefaultEngineVariant(name: InferenceEngine): Promise<DefaultEngineVariant>
abstract getDefaultEngineVariant(
name: InferenceEngine
): Promise<DefaultEngineVariant>

/**
* @body variant - string
Expand Down
108 changes: 20 additions & 88 deletions core/src/node/helper/config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { AppConfiguration, SettingComponentProps } from '../../types'
import { AppConfiguration } from '../../types'
import { join, resolve } from 'path'
import fs from 'fs'
import os from 'os'
import childProcess from 'child_process'
const configurationFileName = 'settings.json'

/**
Expand All @@ -19,7 +18,9 @@ export const getAppConfigurations = (): AppConfiguration => {

if (!fs.existsSync(configurationFile)) {
// create default app config if we don't have one
console.debug(`App config not found, creating default config at ${configurationFile}`)
console.debug(
`App config not found, creating default config at ${configurationFile}`
)
fs.writeFileSync(configurationFile, JSON.stringify(appDefaultConfiguration))
return appDefaultConfiguration
}
Expand All @@ -30,20 +31,28 @@ export const getAppConfigurations = (): AppConfiguration => {
)
return appConfigurations
} catch (err) {
console.error(`Failed to read app config, return default config instead! Err: ${err}`)
console.error(
`Failed to read app config, return default config instead! Err: ${err}`
)
return defaultAppConfig()
}
}

const getConfigurationFilePath = () =>
join(
global.core?.appPath() || process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME'],
global.core?.appPath() ||
process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME'],
configurationFileName
)

export const updateAppConfiguration = (configuration: AppConfiguration): Promise<void> => {
export const updateAppConfiguration = (
configuration: AppConfiguration
): Promise<void> => {
const configurationFile = getConfigurationFilePath()
console.debug('updateAppConfiguration, configurationFile: ', configurationFile)
console.debug(
'updateAppConfiguration, configurationFile: ',
configurationFile
)

fs.writeFileSync(configurationFile, JSON.stringify(configuration))
return Promise.resolve()
Expand All @@ -69,86 +78,6 @@ export const getJanExtensionsPath = (): string => {
return join(appConfigurations.data_folder, 'extensions')
}

/**
* Utility function to physical cpu count
*
* @returns {number} The physical cpu count.
*/
export const physicalCpuCount = async (): Promise<number> => {
const platform = os.platform()
try {
if (platform === 'linux') {
const output = await exec('lscpu -p | egrep -v "^#" | sort -u -t, -k 2,4 | wc -l')
return parseInt(output.trim(), 10)
} else if (platform === 'darwin') {
const output = await exec('sysctl -n hw.physicalcpu_max')
return parseInt(output.trim(), 10)
} else if (platform === 'win32') {
const output = await exec('WMIC CPU Get NumberOfCores')
return output
.split(os.EOL)
.map((line: string) => parseInt(line))
.filter((value: number) => !isNaN(value))
.reduce((sum: number, number: number) => sum + number, 1)
} else {
const cores = os.cpus().filter((cpu: any, index: number) => {
const hasHyperthreading = cpu.model.includes('Intel')
const isOdd = index % 2 === 1
return !hasHyperthreading || isOdd
})
return cores.length
}
} catch (err) {
console.warn('Failed to get physical CPU count', err)
// Divide by 2 to get rid of hyper threading
const coreCount = Math.ceil(os.cpus().length / 2)
console.debug('Using node API to get physical CPU count:', coreCount)
return coreCount
}
}

const exec = async (command: string): Promise<string> => {
return new Promise((resolve, reject) => {
childProcess.exec(command, { encoding: 'utf8' }, (error, stdout) => {
if (error) {
reject(error)
} else {
resolve(stdout)
}
})
})
}

// a hacky way to get the api key. we should comes up with a better
// way to handle this
export const getEngineConfiguration = async (engineId: string) => {
if (engineId !== 'openai' && engineId !== 'groq') return undefined

const settingDirectoryPath = join(
getJanDataFolderPath(),
'settings',
'@janhq',
engineId === 'openai' ? 'inference-openai-extension' : 'inference-groq-extension',
'settings.json'
)

const content = fs.readFileSync(settingDirectoryPath, 'utf-8')
const settings: SettingComponentProps[] = JSON.parse(content)
const apiKeyId = engineId === 'openai' ? 'openai-api-key' : 'groq-api-key'
const keySetting = settings.find((setting) => setting.key === apiKeyId)
let fullUrl = settings.find((setting) => setting.key === 'chat-completions-endpoint')
?.controllerProps.value

let apiKey = keySetting?.controllerProps.value
if (typeof apiKey !== 'string') apiKey = ''
if (typeof fullUrl !== 'string') fullUrl = ''

return {
api_key: apiKey,
full_url: fullUrl,
}
}

/**
* Default app configurations
* App Data Folder default to Electron's userData
Expand All @@ -158,7 +87,10 @@ export const getEngineConfiguration = async (engineId: string) => {
*/
export const defaultAppConfig = (): AppConfiguration => {
const { app } = require('electron')
const defaultJanDataFolder = join(app?.getPath('userData') ?? os?.homedir() ?? '', 'data')
const defaultJanDataFolder = join(
app?.getPath('userData') ?? os?.homedir() ?? '',
'data'
)
return {
data_folder:
process.env.CI === 'e2e'
Expand Down
7 changes: 1 addition & 6 deletions core/src/node/helper/resource.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { SystemResourceInfo } from '../../types'
import { physicalCpuCount } from './config'
import { log } from './logger'

export const getSystemResourceInfo = async (): Promise<SystemResourceInfo> => {
const cpu = await physicalCpuCount()
log(`[CORTEX]::CPU information - ${cpu}`)

return {
numCpuPhysicalCore: cpu,
numCpuPhysicalCore: 0,
memAvailable: 0, // TODO: this should not be 0
}
}
3 changes: 2 additions & 1 deletion core/src/types/engine/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { InferenceEngine } from '../../types'

export type Engines = {
[key in InferenceEngine]: EngineVariant[]
[key in InferenceEngine]: (EngineVariant & EngineConfig)[]
}

export type EngineMetadata = {
Expand Down Expand Up @@ -40,6 +40,7 @@ export type EngineReleased = {
}

export type EngineConfig = {
engine?: string
version?: string
variant?: string
type?: string
Expand Down
18 changes: 14 additions & 4 deletions core/src/types/message/messageEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ export type ThreadMessage = {
completed_at: number
/** The additional metadata of this message. **/
metadata?: Record<string, unknown>

/** Type of the message */
type?: string

/** The error code which explain what error type. Used in conjunction with MessageStatus.Error */
error_code?: ErrorCode
}
Expand Down Expand Up @@ -72,6 +71,10 @@ export type MessageRequest = {
// TODO: deprecate threadId field
thread?: Thread

/** Engine name to process */
engine?: string

/** Message type */
type?: string
}

Expand Down Expand Up @@ -147,7 +150,9 @@ export interface Attachment {
/**
* The tools to add this file to.
*/
tools?: Array<CodeInterpreterTool | Attachment.AssistantToolsFileSearchTypeOnly>
tools?: Array<
CodeInterpreterTool | Attachment.AssistantToolsFileSearchTypeOnly
>
}

export namespace Attachment {
Expand All @@ -166,5 +171,10 @@ export interface IncompleteDetails {
/**
* The reason the message is incomplete.
*/
reason: 'content_filter' | 'max_tokens' | 'run_cancelled' | 'run_expired' | 'run_failed'
reason:
| 'content_filter'
| 'max_tokens'
| 'run_cancelled'
| 'run_expired'
| 'run_failed'
}
27 changes: 27 additions & 0 deletions extensions/engine-management-extension/engines.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import anthropic from './resources/anthropic.json' with { type: 'json' }
import openai from './resources/openai.json' with { type: 'json' }
import openrouter from './resources/openrouter.json' with { type: 'json' }
import groq from './resources/groq.json' with { type: 'json' }
import martian from './resources/martian.json' with { type: 'json' }
import mistral from './resources/mistral.json' with { type: 'json' }
import nvidia from './resources/nvidia.json' with { type: 'json' }

import openaiModels from './models/openai.json' with { type: 'json' }
import anthropicModels from './models/anthropic.json' with { type: 'json' }
import openrouterModels from './models/openrouter.json' with { type: 'json' }
import groqModels from './models/groq.json' with { type: 'json' }
import martianModels from './models/martian.json' with { type: 'json' }
import mistralModels from './models/mistral.json' with { type: 'json' }
import nvidiaModels from './models/nvidia.json' with { type: 'json' }

const engines = [anthropic, openai, openrouter, groq, mistral, martian, nvidia]
const models = [
...openaiModels,
...anthropicModels,
...openrouterModels,
...groqModels,
...mistralModels,
...martianModels,
...nvidiaModels,
]
export { engines, models }
Original file line number Diff line number Diff line change
@@ -1,74 +1,41 @@
[
{
"sources": [
{
"url": "https://www.anthropic.com/"
}
],
"id": "claude-3-opus-latest",
"model": "claude-3-opus-latest",
"object": "model",
"name": "Claude 3 Opus Latest",
"version": "1.0",
"description": "Claude 3 Opus is a powerful model suitables for highly complex task.",
"format": "api",
"settings": {},
"parameters": {
"inference_params": {
"max_tokens": 4096,
"temperature": 0.7,
"stream": false
},
"metadata": {
"author": "Anthropic",
"tags": ["General", "Big Context Length"]
},
"engine": "anthropic"
},
{
"sources": [
{
"url": "https://www.anthropic.com/"
}
],
"id": "claude-3-5-haiku-latest",
"model": "claude-3-5-haiku-latest",
"object": "model",
"name": "Claude 3.5 Haiku Latest",
"version": "1.0",
"description": "Claude 3.5 Haiku is the fastest model provides near-instant responsiveness.",
"format": "api",
"settings": {},
"parameters": {
"inference_params": {
"max_tokens": 8192,
"temperature": 0.7,
"stream": false
},
"metadata": {
"author": "Anthropic",
"tags": ["General", "Big Context Length"]
},
"engine": "anthropic"
},
{
"sources": [
{
"url": "https://www.anthropic.com/"
}
],
"id": "claude-3-5-sonnet-latest",
"model": "claude-3-5-sonnet-latest",
"object": "model",
"name": "Claude 3.5 Sonnet Latest",
"version": "1.0",
"description": "Claude 3.5 Sonnet raises the industry bar for intelligence, outperforming competitor models and Claude 3 Opus on a wide range of evaluations, with the speed and cost of our mid-tier model, Claude 3 Sonnet.",
"format": "api",
"settings": {},
"parameters": {
"inference_params": {
"max_tokens": 8192,
"temperature": 0.7,
"stream": true
},
"metadata": {
"author": "Anthropic",
"tags": ["General", "Big Context Length"]
},
"engine": "anthropic"
}
]
Loading

0 comments on commit e25f6ef

Please sign in to comment.