From 18300a8f13905527886aeca15561630f56626dca Mon Sep 17 00:00:00 2001 From: Zgrill2 Date: Thu, 6 Feb 2025 00:20:52 -0500 Subject: [PATCH 1/9] Add support for GPT models in Azure AI Studio --- profiles/azure.json | 15 +++++++++++++++ src/models/azure.js | 23 +++++++++++++++++++++++ src/models/prompter.js | 5 +++++ 3 files changed, 43 insertions(+) create mode 100644 profiles/azure.json create mode 100644 src/models/azure.js diff --git a/profiles/azure.json b/profiles/azure.json new file mode 100644 index 0000000..fbd382d --- /dev/null +++ b/profiles/azure.json @@ -0,0 +1,15 @@ +{ + "name": "azure", + "model": { + "api": "azure", + "url": "", + "model": "gpt-4o", + "api_version": "2024-08-01-preview" + }, + "embedding": { + "api": "azure", + "url": "", + "model": "text-embedding-ada-002", + "api_version": "2024-08-01-preview" + } +} \ No newline at end of file diff --git a/src/models/azure.js b/src/models/azure.js new file mode 100644 index 0000000..d8e2f4a --- /dev/null +++ b/src/models/azure.js @@ -0,0 +1,23 @@ +import { AzureOpenAI } from "openai"; +import { getKey } from '../utils/keys.js'; +import { GPT } from './gpt.js' + +export class AzureGPT extends GPT { + constructor(model_name, url, api_version, params) { + super(model_name, url) + + this.model_name = model_name; + this.params = params; + + let config = {} + + if (url) + config.endpoint = url; + + config.apiKey = getKey('OPENAI_API_KEY'); + config.deployment = model_name; // This must be what you named the deployment in Azure, not the model version itself + config.apiVersion = api_version; // This is required for Azure + + this.openai = new AzureOpenAI(config) + } +} \ No newline at end of file diff --git a/src/models/prompter.js b/src/models/prompter.js index 5295653..2260ead 100644 --- a/src/models/prompter.js +++ b/src/models/prompter.js @@ -19,6 +19,7 @@ import { HuggingFace } from './huggingface.js'; import { Qwen } from "./qwen.js"; import { Grok } from "./grok.js"; import { DeepSeek } from './deepseek.js'; +import { AzureGPT } from './azure.js'; export class Prompter { constructor(agent, fp) { @@ -72,6 +73,8 @@ export class Prompter { this.embedding_model = new Gemini(embedding.model, embedding.url); else if (embedding.api === 'openai') this.embedding_model = new GPT(embedding.model, embedding.url); + else if (embedding.api === 'azure') + this.embedding_model = new AzureGPT(embedding.model, embedding.url, embedding.api_version); else if (embedding.api === 'replicate') this.embedding_model = new ReplicateAPI(embedding.model, embedding.url); else if (embedding.api === 'ollama') @@ -139,6 +142,8 @@ export class Prompter { model = new Gemini(profile.model, profile.url, profile.params); else if (profile.api === 'openai') model = new GPT(profile.model, profile.url, profile.params); + else if (profile.api === 'azure') + model = new AzureGPT(profile.model, profile.url, profile.api_version, profile.params); else if (profile.api === 'anthropic') model = new Claude(profile.model, profile.url, profile.params); else if (profile.api === 'replicate') From d1bb34446f9d0683a1fea3d52b2beb00633e6028 Mon Sep 17 00:00:00 2001 From: Qu Yi Date: Sun, 20 Apr 2025 11:04:57 +0800 Subject: [PATCH 2/9] New Model Support: Mercury (diffusion large language models) --- README.md | 3 ++- keys.example.json | 3 ++- profiles/mercury.json | 15 +++++++++++++++ src/models/prompter.js | 7 ++++++- 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 profiles/mercury.json diff --git a/README.md b/README.md index 8c4a4e8..ebd251c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Do not connect this bot to public servers with coding enabled. This project allo - [Minecraft Java Edition](https://www.minecraft.net/en-us/store/minecraft-java-bedrock-edition-pc) (up to v1.21.1, recommend v1.20.4) - [Node.js Installed](https://nodejs.org/) (at least v14) -- One of these: [OpenAI API Key](https://openai.com/blog/openai-api) | [Gemini API Key](https://aistudio.google.com/app/apikey) | [Anthropic API Key](https://docs.anthropic.com/claude/docs/getting-access-to-claude) | [Replicate API Key](https://replicate.com/) | [Hugging Face API Key](https://huggingface.co/) | [Groq API Key](https://console.groq.com/keys) | [Ollama Installed](https://ollama.com/download). | [Mistral API Key](https://docs.mistral.ai/getting-started/models/models_overview/) | [Qwen API Key [Intl.]](https://www.alibabacloud.com/help/en/model-studio/developer-reference/get-api-key)/[[cn]](https://help.aliyun.com/zh/model-studio/getting-started/first-api-call-to-qwen?) | [Novita AI API Key](https://novita.ai/settings?utm_source=github_mindcraft&utm_medium=github_readme&utm_campaign=link#key-management) | +- One of these: [OpenAI API Key](https://openai.com/blog/openai-api) | [Gemini API Key](https://aistudio.google.com/app/apikey) | [Anthropic API Key](https://docs.anthropic.com/claude/docs/getting-access-to-claude) | [Replicate API Key](https://replicate.com/) | [Hugging Face API Key](https://huggingface.co/) | [Groq API Key](https://console.groq.com/keys) | [Ollama Installed](https://ollama.com/download). | [Mistral API Key](https://docs.mistral.ai/getting-started/models/models_overview/) | [Qwen API Key [Intl.]](https://www.alibabacloud.com/help/en/model-studio/developer-reference/get-api-key)/[[cn]](https://help.aliyun.com/zh/model-studio/getting-started/first-api-call-to-qwen?) | [Novita AI API Key](https://novita.ai/settings?utm_source=github_mindcraft&utm_medium=github_readme&utm_campaign=link#key-management) | [Mercury API](https://platform.inceptionlabs.ai/docs) ## Install and Run @@ -53,6 +53,7 @@ You can configure the agent's name, model, and prompts in their profile like `an | `openrouter` | `OPENROUTER_API_KEY` | `openrouter/anthropic/claude-3.5-sonnet` | [docs](https://openrouter.ai/models) | | `glhf.chat` | `GHLF_API_KEY` | `glhf/hf:meta-llama/Llama-3.1-405B-Instruct` | [docs](https://glhf.chat/user-settings/api) | | `hyperbolic` | `HYPERBOLIC_API_KEY` | `hyperbolic/deepseek-ai/DeepSeek-V3` | [docs](https://docs.hyperbolic.xyz/docs/getting-started) | +| `mercury(EA)` | `MERCURY_API_KEY` | `mercury-coder-small` | [docs](https://www.inceptionlabs.ai/) | If you use Ollama, to install the models used by default (generation and embedding), execute the following terminal command: `ollama pull llama3.1 && ollama pull nomic-embed-text` diff --git a/keys.example.json b/keys.example.json index 99286c5..eb08814 100644 --- a/keys.example.json +++ b/keys.example.json @@ -13,5 +13,6 @@ "GHLF_API_KEY": "", "HYPERBOLIC_API_KEY": "", "NOVITA_API_KEY": "", - "OPENROUTER_API_KEY": "" + "OPENROUTER_API_KEY": "", + "MERCURY_API_KEY":"" } diff --git a/profiles/mercury.json b/profiles/mercury.json new file mode 100644 index 0000000..cac6d49 --- /dev/null +++ b/profiles/mercury.json @@ -0,0 +1,15 @@ +{ + "name": "Mercury", + + "cooldown": 5000, + + "model": { + "api": "mercury", + "url": "https://api.inceptionlabs.ai/v1", + "model": "mercury-coder-small" + }, + + "embedding": "openai", + + "description":"Official Website Introduction:The world’s first diffusion large language models" +} \ No newline at end of file diff --git a/src/models/prompter.js b/src/models/prompter.js index 46f7760..e988fc1 100644 --- a/src/models/prompter.js +++ b/src/models/prompter.js @@ -21,6 +21,7 @@ import { DeepSeek } from './deepseek.js'; import { Hyperbolic } from './hyperbolic.js'; import { GLHF } from './glhf.js'; import { OpenRouter } from './openrouter.js'; +import { Mercury} from "./mercury.js"; export class Prompter { constructor(agent, fp) { @@ -159,8 +160,10 @@ export class Prompter { profile.api = 'xai'; else if (profile.model.includes('deepseek')) profile.api = 'deepseek'; - else if (profile.model.includes('mistral')) + else if (profile.model.includes('mistral')) profile.api = 'mistral'; + else if (profile.model.includes('mercury')) + profile.api = 'mercury'; else throw new Error('Unknown model:', profile.model); } @@ -198,6 +201,8 @@ export class Prompter { model = new DeepSeek(profile.model, profile.url, profile.params); else if (profile.api === 'openrouter') model = new OpenRouter(profile.model.replace('openrouter/', ''), profile.url, profile.params); + else if (profile.api === 'mercury') + model = new Mercury(profile.model, profile.url, profile.params); else throw new Error('Unknown API:', profile.api); return model; From a100486896f5a69849148aa0a52994fbd3e2bc9c Mon Sep 17 00:00:00 2001 From: Qu Yi Date: Sun, 20 Apr 2025 11:06:31 +0800 Subject: [PATCH 3/9] Add `mercury.js` --- src/models/mercury.js | 92 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/models/mercury.js diff --git a/src/models/mercury.js b/src/models/mercury.js new file mode 100644 index 0000000..485cc8d --- /dev/null +++ b/src/models/mercury.js @@ -0,0 +1,92 @@ +import OpenAIApi from 'openai'; +import { getKey, hasKey } from '../utils/keys.js'; +import { strictFormat } from '../utils/text.js'; + +export class Mercury { + constructor(model_name, url, params) { + this.model_name = model_name; + this.params = params; + let config = {}; + if (url) + config.baseURL = url; + + config.apiKey = getKey('MERCURY_API_KEY'); + + this.openai = new OpenAIApi(config); + } + + async sendRequest(turns, systemMessage, stop_seq='***') { + if (typeof stop_seq === 'string') { + stop_seq = [stop_seq]; + } else if (!Array.isArray(stop_seq)) { // 处理其他非字符串非数组的无效输入 + stop_seq = []; // 或抛出错误,或其他处理方式 + } + let messages = [{'role': 'system', 'content': systemMessage}].concat(turns); + messages = strictFormat(messages); + const pack = { + model: this.model_name || "mercury-coder-small", + messages, + stop: stop_seq, + ...(this.params || {}) + }; + + + let res = null; + + try { + console.log('Awaiting mercury api response from model', this.model_name) + // console.log('Messages:', messages); + let completion = await this.openai.chat.completions.create(pack); + if (completion.choices[0].finish_reason == 'length') + throw new Error('Context length exceeded'); + console.log('Received.') + res = completion.choices[0].message.content; + } + catch (err) { + if ((err.message == 'Context length exceeded' || err.code == 'context_length_exceeded') && turns.length > 1) { + console.log('Context length exceeded, trying again with shorter context.'); + return await this.sendRequest(turns.slice(1), systemMessage, stop_seq); + } else if (err.message.includes('image_url')) { + console.log(err); + res = 'Vision is only supported by certain models.'; + } else { + console.log(err); + res = 'My brain disconnected, try again.'; + } + } + return res; + } + + async sendVisionRequest(messages, systemMessage, imageBuffer) { + const imageMessages = [...messages]; + imageMessages.push({ + role: "user", + content: [ + { type: "text", text: systemMessage }, + { + type: "image_url", + image_url: { + url: `data:image/jpeg;base64,${imageBuffer.toString('base64')}` + } + } + ] + }); + + return this.sendRequest(imageMessages, systemMessage); + } + + async embed(text) { + if (text.length > 8191) + text = text.slice(0, 8191); + const embedding = await this.openai.embeddings.create({ + model: this.model_name || "text-embedding-3-small", + input: text, + encoding_format: "float", + }); + return embedding.data[0].embedding; + } + +} + + + From 23095ce0ed4121e6f1fa84619202922fa132b204 Mon Sep 17 00:00:00 2001 From: Qu Yi Date: Sun, 20 Apr 2025 11:41:04 +0800 Subject: [PATCH 4/9] Update `mercury.js` --- src/models/mercury.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/models/mercury.js b/src/models/mercury.js index 485cc8d..d4c4c3e 100644 --- a/src/models/mercury.js +++ b/src/models/mercury.js @@ -18,8 +18,8 @@ export class Mercury { async sendRequest(turns, systemMessage, stop_seq='***') { if (typeof stop_seq === 'string') { stop_seq = [stop_seq]; - } else if (!Array.isArray(stop_seq)) { // 处理其他非字符串非数组的无效输入 - stop_seq = []; // 或抛出错误,或其他处理方式 + } else if (!Array.isArray(stop_seq)) { + stop_seq = []; } let messages = [{'role': 'system', 'content': systemMessage}].concat(turns); messages = strictFormat(messages); From b1932cf93e7b02f0190fc3455dcb0dda48791aca Mon Sep 17 00:00:00 2001 From: Qu Yi Date: Fri, 2 May 2025 09:50:48 +0800 Subject: [PATCH 5/9] feat:add new model support `mercury`(diffusion large language models) --- settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.js b/settings.js index b782097..55cbf4d 100644 --- a/settings.js +++ b/settings.js @@ -21,6 +21,7 @@ const settings = { // "./profiles/grok.json", // "./profiles/mistral.json", // "./profiles/deepseek.json", + //"./profiles/mercury.json", // using more than 1 profile requires you to /msg each bot indivually // individual profiles override values from the base profile From f41f03cdb324dfd67930e7f67325ee70cce5191d Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 23 Aug 2025 15:40:16 -0500 Subject: [PATCH 6/9] clean up mercury --- README.md | 2 +- profiles/mercury.json | 10 ++-------- src/models/mercury.js | 3 +++ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b1ff8cb..191b21a 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ You can configure the agent's name, model, and prompts in their profile like `an | `hyperbolic` | `HYPERBOLIC_API_KEY` | `hyperbolic/deepseek-ai/DeepSeek-V3` | [docs](https://docs.hyperbolic.xyz/docs/getting-started) | | `vllm` | n/a | `vllm/llama3` | n/a | | `cerebras` | `CEREBRAS_API_KEY` | `cerebras/llama-3.3-70b` | [docs](https://inference-docs.cerebras.ai/introduction) | -| `mercury(EA)` | `MERCURY_API_KEY` | `mercury-coder-small` | [docs](https://www.inceptionlabs.ai/) | +| `mercury` | `MERCURY_API_KEY` | `mercury-coder-small` | [docs](https://www.inceptionlabs.ai/) | If you use Ollama, to install the models used by default (generation and embedding), execute the following terminal command: `ollama pull llama3.1 && ollama pull nomic-embed-text` diff --git a/profiles/mercury.json b/profiles/mercury.json index cac6d49..482b601 100644 --- a/profiles/mercury.json +++ b/profiles/mercury.json @@ -3,13 +3,7 @@ "cooldown": 5000, - "model": { - "api": "mercury", - "url": "https://api.inceptionlabs.ai/v1", - "model": "mercury-coder-small" - }, + "model": "mercury/mercury-coder-small", - "embedding": "openai", - - "description":"Official Website Introduction:The world’s first diffusion large language models" + "embedding": "openai" } \ No newline at end of file diff --git a/src/models/mercury.js b/src/models/mercury.js index d4c4c3e..74cd64e 100644 --- a/src/models/mercury.js +++ b/src/models/mercury.js @@ -3,12 +3,15 @@ import { getKey, hasKey } from '../utils/keys.js'; import { strictFormat } from '../utils/text.js'; export class Mercury { + static prefix = 'mercury'; constructor(model_name, url, params) { this.model_name = model_name; this.params = params; let config = {}; if (url) config.baseURL = url; + else + config.baseURL = "https://api.inceptionlabs.ai/v1"; config.apiKey = getKey('MERCURY_API_KEY'); From 1588a8770bd7290d2a9ea9cc6b997239f5ea85bf Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 23 Aug 2025 16:00:59 -0500 Subject: [PATCH 7/9] clean up azure --- profiles/azure.json | 18 +++++++++++------- src/models/azure.js | 23 ++++++++++++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/profiles/azure.json b/profiles/azure.json index fbd382d..29b1122 100644 --- a/profiles/azure.json +++ b/profiles/azure.json @@ -2,14 +2,18 @@ "name": "azure", "model": { "api": "azure", - "url": "", - "model": "gpt-4o", - "api_version": "2024-08-01-preview" + "url": "https://.openai.azure.com", + "model": "", + "params": { + "apiVersion": "2024-08-01-preview" + } }, "embedding": { "api": "azure", - "url": "", - "model": "text-embedding-ada-002", - "api_version": "2024-08-01-preview" + "url": "https://.openai.azure.com", + "model": "", + "params": { + "apiVersion": "2024-08-01-preview" + } } -} \ No newline at end of file + } \ No newline at end of file diff --git a/src/models/azure.js b/src/models/azure.js index d8e2f4a..b6be3e0 100644 --- a/src/models/azure.js +++ b/src/models/azure.js @@ -1,22 +1,31 @@ import { AzureOpenAI } from "openai"; -import { getKey } from '../utils/keys.js'; +import { getKey, hasKey } from '../utils/keys.js'; import { GPT } from './gpt.js' export class AzureGPT extends GPT { - constructor(model_name, url, api_version, params) { + static prefix = 'azure'; + constructor(model_name, url, params) { super(model_name, url) this.model_name = model_name; - this.params = params; + this.params = params || {}; - let config = {} + const config = {}; if (url) config.endpoint = url; - config.apiKey = getKey('OPENAI_API_KEY'); - config.deployment = model_name; // This must be what you named the deployment in Azure, not the model version itself - config.apiVersion = api_version; // This is required for Azure + config.apiKey = hasKey('AZURE_OPENAI_API_KEY') ? getKey('AZURE_OPENAI_API_KEY') : getKey('OPENAI_API_KEY'); + + config.deployment = model_name; + + if (this.params.apiVersion) { + config.apiVersion = this.params.apiVersion; + delete this.params.apiVersion; // remove from params for later use in requests + } + else { + throw new Error('apiVersion is required in params for azure!'); + } this.openai = new AzureOpenAI(config) } From 5f3a7f98c4aa1a994bbf29180a9aca244b3fac21 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 23 Aug 2025 16:13:04 -0500 Subject: [PATCH 8/9] fix default claude models --- profiles/claude.json | 2 +- profiles/claude_thinker.json | 2 +- src/models/claude.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/profiles/claude.json b/profiles/claude.json index 27f610d..b1a324d 100644 --- a/profiles/claude.json +++ b/profiles/claude.json @@ -1,7 +1,7 @@ { "name": "claude", - "model": "claude-4-sonnet-latest", + "model": "claude-sonnet-4-20250514", "embedding": "openai" } \ No newline at end of file diff --git a/profiles/claude_thinker.json b/profiles/claude_thinker.json index 64e3fb4..49df53f 100644 --- a/profiles/claude_thinker.json +++ b/profiles/claude_thinker.json @@ -2,7 +2,7 @@ "name": "claude_thinker", "model": { - "model": "claude-4-sonnet-latest", + "model": "claude-sonnet-4-20250514", "params": { "thinking": { "type": "enabled", diff --git a/src/models/claude.js b/src/models/claude.js index c42d2e6..271c6b2 100644 --- a/src/models/claude.js +++ b/src/models/claude.js @@ -21,7 +21,7 @@ export class Claude { const messages = strictFormat(turns); let res = null; try { - console.log('Awaiting anthropic api response...') + console.log(`Awaiting anthropic response from ${this.model_name}...`) if (!this.params.max_tokens) { if (this.params.thinking?.budget_tokens) { this.params.max_tokens = this.params.thinking.budget_tokens + 1000; @@ -31,7 +31,7 @@ export class Claude { } } const resp = await this.anthropic.messages.create({ - model: this.model_name || "claude-3-sonnet-20240229", + model: this.model_name || "claude-sonnet-4-20250514", system: systemMessage, messages: messages, ...(this.params || {}) From 0e990af01fa9cc39dcf96c9e23f26c969620754b Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 23 Aug 2025 16:14:30 -0500 Subject: [PATCH 9/9] add azure instructions --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 191b21a..11a2894 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ You can configure the agent's name, model, and prompts in their profile like `an If you use Ollama, to install the models used by default (generation and embedding), execute the following terminal command: `ollama pull llama3.1 && ollama pull nomic-embed-text` +To use Azure, you can reuse the `OPENAI_API_KEY` environment variable. You can get the key from the Azure portal. See [azure.json](profiles/azure.json) for an example. + ### Online Servers To connect to online servers your bot will need an official Microsoft/Minecraft account. You can use your own personal one, but will need another account if you want to connect too and play with it. To connect, change these lines in `settings.js`: ```javascript