增加多种配置文件格式支持

main
落雨楓 6 months ago
parent ba06f46898
commit b3fb6186e5

4
.gitignore vendored

@ -1,3 +1,5 @@
node_modules/
/dist/
/config.yaml
/config.yaml
/config.jsonc
/config.json5

@ -0,0 +1,19 @@
{
"$schema": "schemas/ServerConfig.json",
"port": 6800,
"db_type": "postgres",
"db": {
"host": "localhost",
"port": 5432,
"user": "memory_proxy",
"password": "memory_proxy",
"database": "memory_proxy"
},
"memory_max_messages": 1000,
"proxies": {
"deepseek": {
"endpoint": "https://api.deepseek.com",
"type": "openai"
}
}
}

@ -0,0 +1 @@
import '#app/cli/ExportSchemas';

@ -1,3 +1,3 @@
import App from '#app/App';
new App("./config.yaml");
new App();

@ -5,6 +5,7 @@
"main": "index.js",
"type": "module",
"scripts": {
"exportSchema": "npx tsx export-schema.js",
"start": "node index.js",
"dev": "npx tsx index.js",
"build": "tsc && node post-build.js"
@ -20,6 +21,7 @@
"extensionless": "^1.9.9",
"got": "^14.4.7",
"hpagent": "^1.2.0",
"json5": "^2.2.3",
"koa": "^3.0.0",
"koa-body": "^6.0.1",
"koa-logger": "^3.2.1",
@ -33,6 +35,7 @@
"yaml": "^1.10.2"
},
"devDependencies": {
"@bpinternal/zod-to-json-schema": "^3.22.5",
"@types/koa": "^2.15.0",
"@types/koa-logger": "^3.1.5",
"@types/koa-router": "^7.4.8",

File diff suppressed because it is too large Load Diff

@ -0,0 +1,99 @@
{
"type": "object",
"properties": {
"debug": {
"type": "boolean",
"description": "Whether to enable debug mode."
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"description": "The server port."
},
"memory_max_messages": {
"type": "integer",
"minimum": 1,
"description": "The maximum number of messages to remember."
},
"db_type": {
"type": "string",
"enum": [
"postgres"
],
"description": "The type of database, currently only supports Postgres."
},
"db": {
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "The host of the Postgres database."
},
"port": {
"type": "integer",
"description": "The port of the Postgres database."
},
"user": {
"type": "string",
"description": "The username for the Postgres database."
},
"password": {
"type": "string",
"description": "The password for the Postgres database."
},
"database": {
"type": "string",
"description": "The name of the Postgres database."
}
},
"additionalProperties": false,
"description": "Configuration for the Postgres database."
},
"proxies": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of the LLM proxy, e.g., \"openai\", \"azure\", etc."
},
"endpoint": {
"type": "string",
"description": "The endpoint URL of the LLM proxy."
},
"http_proxy": {
"type": "string",
"description": "Optional HTTP proxy URL for the LLM proxy."
},
"socks_proxy": {
"type": "string",
"description": "Optional SOCKS proxy URL for the LLM proxy."
}
},
"required": [
"type",
"endpoint"
],
"additionalProperties": false
},
"description": "A record of LLM proxy configurations."
},
"api_keys": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of API keys for authentication."
}
},
"required": [
"port",
"memory_max_messages",
"proxies",
"api_keys"
],
"additionalProperties": true,
"$schema": "http://json-schema.org/draft-07/schema#"
}

@ -3,6 +3,7 @@ import 'reflect-metadata';
import * as fs from 'node:fs';
import winston from 'winston';
import Yaml from 'yaml';
import Json5 from 'json5';
import { Logger } from '#app/utils/logger.js';
import Koa, { Next } from 'koa';
import Router from 'koa-router';
@ -11,7 +12,7 @@ import { koaBody } from 'koa-body';
import { EchoBackController } from './controllers/EchoBackController.js';
import { DataSource } from 'typeorm';
import { Entities } from './entity/index.js';
import { ServerConfig } from './types/ServerConfig.js';
import { ServerConfig } from './schemas/ServerConfig.js';
import { LLMApiProxies } from './proxies/index.js';
import { MemoryController } from './controllers/MemoryController.js';
import { swaggerRouter } from './router.js';
@ -35,7 +36,7 @@ export default class App {
public db: DataSource | null = null;
constructor(configPath: string) {
constructor(configPath: string = "") {
this.loadConfig(configPath);
this.init()
@ -53,14 +54,57 @@ export default class App {
this.start();
}
private loadConfig(configPath: string): void {
let configText = fs.readFileSync(configPath, 'utf-8');
let localConfig = Yaml.parse(configText);
private loadConfig(configPath: string = ""): void {
const defaultConfigPaths = [
'./config.json',
'./config.jsonc',
'./config.json5',
'./config.yaml',
]
this.config = {
...this.config,
...localConfig,
};
const configParserMap = {
"json": JSON.parse,
"jsonc": Json5.parse,
"json5": Json5.parse,
"yaml": Yaml.parse,
}
if (!configPath) {
// 如果没有提供配置路径,则尝试加载默认配置文件
for (const defaultPath of defaultConfigPaths) {
if (fs.existsSync(defaultPath)) {
configPath = defaultPath;
break;
}
}
}
if (!configPath) {
console.error(`No configuration file found.`);
process.exit(1); // 退出程序
}
const fileExtension = configPath.split('.').pop()?.toLowerCase();
const parser = configParserMap[fileExtension as keyof typeof configParserMap];
if (!parser) {
console.error(`Unsupported configuration file format: ${fileExtension}`);
process.exit(1); // 退出程序
}
try {
console.log(`Loading configuration from ${configPath}`);
let configText = fs.readFileSync(configPath, 'utf-8');
this.config = parser(configText);
} catch (error) {
console.error(`Failed to parse config file ${configPath}:`, error);
process.exit(1); // 退出程序
}
if (!this.config) {
console.error(`No valid configuration found in ${configPath}`);
process.exit(1); // 退出程序
}
this.debug = this.config?.debug || false; // 从配置中读取调试模式
}

@ -0,0 +1,21 @@
import { ServerConfigSchema } from "#app/schemas/ServerConfig.js";
import { z } from "koa-swagger-decorator";
import { zodToJsonSchema } from "@bpinternal/zod-to-json-schema";
import fs from 'fs';
const schemaMap = {
'ServerConfig': ServerConfigSchema,
}
const outputDir = './schemas'; // 输出目录
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
for (let [name, schema] of Object.entries(schemaMap)) {
// 导出为 JSON 文件
const outputFile = `${outputDir}/${name}.json`;
console.log(`Exporting schema ${name} to ${outputFile}`);
fs.writeFileSync(outputFile, JSON.stringify(zodToJsonSchema(schema), null, 2));
}

@ -1,5 +1,5 @@
import App from "#app/App.js";
import { LLMProxyConfig } from "#app/types/ServerConfig.js";
import { LLMProxyConfig } from "#app/schemas/ServerConfig.js";
import Router from "koa-router";
export class BaseLLMProxy {

@ -1,5 +1,5 @@
import App from "#app/App.js";
import { LLMProxyConfig } from "#app/types/ServerConfig.js";
import { LLMProxyConfig } from "#app/schemas/ServerConfig.js";
import { Logger } from "#app/utils/logger.js";
import Koa, { Next } from "koa";
import Router from "koa-router";

@ -0,0 +1,32 @@
import { z } from 'koa-swagger-decorator';
export const LLMProxyConfigSchema = z.object({
type: z.string().describe('The type of the LLM proxy, e.g., "openai", "azure", etc.'),
endpoint: z.string().describe('The endpoint URL of the LLM proxy.'),
http_proxy: z.string().optional().describe('Optional HTTP proxy URL for the LLM proxy.'),
socks_proxy: z.string().optional().describe('Optional SOCKS proxy URL for the LLM proxy.'),
});
export type LLMProxyConfig = z.infer<typeof LLMProxyConfigSchema>;
export const PostgresDatabaseConfigSchema = z.object({
host: z.string().optional().describe('The host of the Postgres database.'),
port: z.number().int().optional().describe('The port of the Postgres database.'),
user: z.string().optional().describe('The username for the Postgres database.'),
password: z.string().optional().describe('The password for the Postgres database.'),
database: z.string().optional().describe('The name of the Postgres database.'),
});
export type PostgresDatabaseConfig = z.infer<typeof PostgresDatabaseConfigSchema>;
export const ServerConfigSchema = z.object({
debug: z.boolean().optional().describe('Whether to enable debug mode.'),
port: z.number().int().min(1).max(65535).describe('The server port.'),
memory_max_messages: z.number().int().min(1).describe('The maximum number of messages to remember.'),
db_type: z.enum(['postgres']).optional().describe('The type of database, currently only supports Postgres.'),
db: PostgresDatabaseConfigSchema.optional().describe('Configuration for the Postgres database.'),
proxies: z.record(LLMProxyConfigSchema).describe('A record of LLM proxy configurations.'),
api_keys: z.array(z.string()).describe('A list of API keys for authentication.'),
}).passthrough();
export type ServerConfig = z.infer<typeof ServerConfigSchema>;

@ -1,24 +0,0 @@
export interface LLMProxyConfig {
type: string;
endpoint: string;
http_proxy?: string;
socks_proxy?: string;
}
export interface PostgresDatabaseConfig {
host?: string;
port?: number;
user?: string;
password?: string;
database?: string;
}
export interface ServerConfig {
debug?: boolean; // 是否开启调试模式
port: number; // 服务器端口
memory_max_messages: number; // 记忆中的最大消息数
db_type?: "postgres"; // 数据库类型,目前只支持 Postgres
db?: PostgresDatabaseConfig;
proxies: Record<string, LLMProxyConfig>;
api_keys: string[];
}
Loading…
Cancel
Save