symmetry-core
Version:
Use this repository to become an inference provider on the Symmetry network programmatically.
131 lines (130 loc) • 5.18 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseProvider = void 0;
const promises_1 = __importDefault(require("fs/promises"));
const path_1 = __importDefault(require("path"));
const net_1 = __importDefault(require("net"));
const os_1 = __importDefault(require("os"));
const node_crypto_1 = __importDefault(require("node:crypto"));
const js_yaml_1 = __importDefault(require("js-yaml"));
const readline_1 = __importDefault(require("readline"));
const logger_1 = require("../logger");
class BaseProvider {
constructor() {
this.serverConfig = {
apiProtocol: "http",
apiHostname: "localhost",
apiModelsPath: "/v1/models",
apiBasePath: "/v1",
systemMessage: "You are a helpful AI assistant.",
serverKey: node_crypto_1.default.randomBytes(32).toString("hex"),
userSecret: node_crypto_1.default.randomBytes(16).toString("hex"),
};
}
static async promptUser(question) {
const rl = readline_1.default.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => {
rl.question(question, (answer) => {
rl.close();
resolve(answer);
});
});
}
async checkPort(port) {
if (!port)
return false;
return new Promise((resolve) => {
const socket = new net_1.default.Socket();
const onError = () => {
socket.destroy();
resolve(false);
};
socket.setTimeout(1000);
socket.once("error", onError);
socket.once("timeout", onError);
socket.connect(port, "localhost", () => {
socket.end();
resolve(true);
});
});
}
async getModels(apiKey) {
const path = `${this.serverConfig.apiProtocol}://${this.serverConfig.apiHostname}:${this.serverConfig.apiPort}${this.serverConfig.apiModelsPath}`;
try {
const response = await fetch(path, {
headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
});
if (!response.ok)
throw new Error(`Failed to fetch models: ${response.statusText}`);
const data = (await response.json());
return data.data;
}
catch (error) {
logger_1.logger.error("Failed to fetch models");
return [];
}
}
async createConfig(server) {
const configDir = path_1.default.join(BaseProvider.DEFAULT_CONFIG_PATH);
const dataDir = path_1.default.join(configDir, "data");
const config = this.generateConfig(server);
try {
await promises_1.default.mkdir(configDir, { recursive: true });
await promises_1.default.mkdir(dataDir, { recursive: true });
await promises_1.default.writeFile(path_1.default.join(configDir, "provider.yaml"), js_yaml_1.default.dump(config), "utf-8");
}
catch (error) {
logger_1.logger.error(`Failed to create config file: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
generateConfig(server) {
return {
name: `symmetry-${server.name}`,
public: true,
maxConnections: 10,
apiHostname: "localhost",
apiPort: server.apiPort,
apiProtocol: "http",
apiBasePath: server.apiBasePath,
modelName: server.modelName,
systemMessage: "You are a helpful AI assistant.",
serverKey: "4b4a9cc325d134dee6679e9407420023531fd7e96c563f6c5d00fd5549b77435",
userSecret: node_crypto_1.default.randomBytes(16).toString("hex"),
};
}
async selectModel(models) {
if (models.length === 0)
return "";
console.log("\nAvailable models:");
models.forEach((model, index) => {
console.log(`${index + 1}. ${model.id}`);
});
const selection = await BaseProvider.promptUser("\nSelect a model (enter number): ");
const index = parseInt(selection) - 1;
if (index >= 0 && index < models.length) {
return models[index].id;
}
return "gpt-3.5-turbo";
}
async detectServer() {
try {
const isPortOpen = await this.checkPort(this.serverConfig.apiPort);
if (!isPortOpen)
return null;
const response = await fetch(`${this.serverConfig.apiProtocol}://${this.serverConfig.apiHostname}:${this.serverConfig.apiPort}${this.serverConfig.apiHealthPath}`);
return response.ok ? this.serverConfig : null;
}
catch (_a) {
return null;
}
}
}
exports.BaseProvider = BaseProvider;
BaseProvider.DEFAULT_CONFIG_PATH = path_1.default.join(os_1.default.homedir(), ".config", "symmetry");