Add AI Horde client library

This commit is contained in:
SillyLossy
2023-05-15 21:24:17 +03:00
parent c3146e830d
commit f86ee330a7
4 changed files with 105 additions and 24 deletions

30
package-lock.json generated
View File

@ -10,6 +10,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"@dqbd/tiktoken": "^1.0.2", "@dqbd/tiktoken": "^1.0.2",
"@zeldafan0225/ai_horde": "^4.0.1",
"axios": "^1.3.4", "axios": "^1.3.4",
"command-exists": "^1.2.9", "command-exists": "^1.2.9",
"compression": "^1", "compression": "^1",
@ -418,6 +419,11 @@
"regenerator-runtime": "^0.13.3" "regenerator-runtime": "^0.13.3"
} }
}, },
"node_modules/@thunder04/supermap": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@thunder04/supermap/-/supermap-3.0.2.tgz",
"integrity": "sha512-SjlUrfe45mwiAgKZHRRhh+oHRwXsjrCg6NI2HJxymTJt+9SwJw422yse/A5lr5WBpTky6qEce+H6Ec1sytm93A=="
},
"node_modules/@tokenizer/token": { "node_modules/@tokenizer/token": {
"version": "0.3.0", "version": "0.3.0",
"license": "MIT" "license": "MIT"
@ -434,6 +440,16 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/@zeldafan0225/ai_horde": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@zeldafan0225/ai_horde/-/ai_horde-4.0.1.tgz",
"integrity": "sha512-mf1cknnBYzKCvgH4KAkdVY3J7sLkR2b79W6I9ZEA2aJCyua28bpZzNaCDSHKKyaNj+0wyHViC+L53X32jw9pMg==",
"dependencies": {
"@thunder04/supermap": "^3.0.2",
"centra": "^2.5.0",
"esbuild": "^0.12.28"
}
},
"node_modules/accepts": { "node_modules/accepts": {
"version": "1.3.8", "version": "1.3.8",
"license": "MIT", "license": "MIT",
@ -621,6 +637,11 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/centra": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/centra/-/centra-2.6.0.tgz",
"integrity": "sha512-dgh+YleemrT8u85QL11Z6tYhegAs3MMxsaWAq/oXeAmYJ7VxL3SI9TZtnfaEvNDMAPolj25FXIb3S+HCI4wQaQ=="
},
"node_modules/cliui": { "node_modules/cliui": {
"version": "8.0.1", "version": "8.0.1",
"license": "ISC", "license": "ISC",
@ -872,6 +893,15 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/esbuild": {
"version": "0.12.29",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.29.tgz",
"integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==",
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
}
},
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.1.1", "version": "3.1.1",
"license": "MIT", "license": "MIT",

View File

@ -1,6 +1,7 @@
{ {
"dependencies": { "dependencies": {
"@dqbd/tiktoken": "^1.0.2", "@dqbd/tiktoken": "^1.0.2",
"@zeldafan0225/ai_horde": "^4.0.1",
"axios": "^1.3.4", "axios": "^1.3.4",
"command-exists": "^1.2.9", "command-exists": "^1.2.9",
"compression": "^1", "compression": "^1",

View File

@ -1,10 +1,10 @@
{ {
"display_name": "Stable Diffusion", "display_name": "Stable Diffusion",
"loading_order": 10, "loading_order": 10,
"requires": [ "requires": [],
"optional": [
"sd" "sd"
], ],
"optional": [],
"js": "index.js", "js": "index.js",
"css": "style.css", "css": "style.css",
"author": "Cohee#1207", "author": "Cohee#1207",

View File

@ -82,6 +82,10 @@ const allowKeysExposure = config.allowKeysExposure;
const axios = require('axios'); const axios = require('axios');
const tiktoken = require('@dqbd/tiktoken'); const tiktoken = require('@dqbd/tiktoken');
const WebSocket = require('ws'); const WebSocket = require('ws');
const AIHorde = require("@zeldafan0225/ai_horde");
const ai_horde = new AIHorde({
client_agent: getVersion()?.agent || 'SillyTavern:UNKNOWN:Cohee#1207',
});
var Client = require('node-rest-client').Client; var Client = require('node-rest-client').Client;
var client = new Client(); var client = new Client();
@ -309,27 +313,8 @@ app.get('/deviceinfo', function (request, response) {
return response.send(deviceInfo); return response.send(deviceInfo);
}); });
app.get('/version', function (_, response) { app.get('/version', function (_, response) {
let pkgVersion, gitRevision, gitBranch; const data = getVersion();
try { response.send(data);
const pkgJson = require('./package.json');
pkgVersion = pkgJson.version;
if (commandExistsSync('git')) {
gitRevision = require('child_process')
.execSync('git rev-parse --short HEAD', { cwd: __dirname })
.toString().trim();
gitBranch = require('child_process')
.execSync('git rev-parse --abbrev-ref HEAD', { cwd: __dirname })
.toString().trim();
}
}
catch {
// suppress exception
}
finally {
const agent = `SillyTavern:${gitRevision || pkgVersion}:Cohee#1207`;
response.send({ agent, pkgVersion, gitRevision, gitBranch });
}
}) })
//**************Kobold api //**************Kobold api
@ -665,6 +650,31 @@ app.post("/setsoftprompt", jsonParser, async function (request, response) {
return response.sendStatus(200); return response.sendStatus(200);
}); });
function getVersion() {
let pkgVersion = 'UNKNOWN';
let gitRevision = null;
let gitBranch = null;
try {
const pkgJson = require('./package.json');
pkgVersion = pkgJson.version;
if (commandExistsSync('git')) {
gitRevision = require('child_process')
.execSync('git rev-parse --short HEAD', { cwd: __dirname })
.toString().trim();
gitBranch = require('child_process')
.execSync('git rev-parse --abbrev-ref HEAD', { cwd: __dirname })
.toString().trim();
}
}
catch {
// suppress exception
}
const agent = `SillyTavern:${pkgVersion}:Cohee#1207`;
return { agent, pkgVersion, gitRevision, gitBranch };
}
function tryParse(str) { function tryParse(str) {
try { try {
return json5.parse(str); return json5.parse(str);
@ -2870,8 +2880,9 @@ app.post('/readsecretstate', jsonParser, (_, response) => {
} }
}); });
const ANONYMOUS_KEY = "0000000000";
app.post('/generate_horde', jsonParser, async (request, response) => { app.post('/generate_horde', jsonParser, async (request, response) => {
const ANONYMOUS_KEY = "0000000000";
const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY; const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY;
const url = 'https://horde.koboldai.net/api/v2/generate/text/async'; const url = 'https://horde.koboldai.net/api/v2/generate/text/async';
@ -2914,6 +2925,45 @@ app.post('/viewsecrets', jsonParser, async (_, response) => {
} }
}); });
app.post('/horde_generateimage', async (request, response) => {
const MAX_ATTEMPTS = 100;
const CHECK_INTERVAL = 3000;
const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY;
const generation = await ai_horde.postAsyncImageGenerate(
{
prompt: `${request.body.prompt_prefix} ${request.body.prompt} ### ${request.body.negative_prompt}`,
params:
{
sampler_name: request.body.sampler,
cfg_scale: request.body.scale,
steps: request.body.steps,
width: request.body.width,
height: request.body.height,
n: 1,
},
r2: false,
nsfw: request.body.nfsw,
models: [request.body.model],
},
{ token: api_key_horde });
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
await delay(CHECK_INTERVAL);
const check = await ai_horde.getImageGenerationCheck(generation.id);
if (check.done) {
const result = await ai_horde.getImageGenerationStatus(generation.id);
return response.send(result.generations[0].img);
}
if (check.faulted) {
return response.sendStatus(500);
}
}
return response.sendStatus(504);
});
function writeSecret(key, value) { function writeSecret(key, value) {
if (!fs.existsSync(SECRETS_FILE)) { if (!fs.existsSync(SECRETS_FILE)) {
const emptyFile = JSON.stringify({}); const emptyFile = JSON.stringify({});