mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-04-22 06:02:07 +02:00
Merge pull request #430 from kolbytn/model_params
Model Params + Updated Gemini
This commit is contained in:
commit
116b7ac83e
19 changed files with 156 additions and 135 deletions
37
README.md
37
README.md
|
@ -41,7 +41,7 @@ You can configure the agent's name, model, and prompts in their profile like `an
|
||||||
| OpenAI | `OPENAI_API_KEY` | `gpt-4o-mini` | [docs](https://platform.openai.com/docs/models) |
|
| OpenAI | `OPENAI_API_KEY` | `gpt-4o-mini` | [docs](https://platform.openai.com/docs/models) |
|
||||||
| Google | `GEMINI_API_KEY` | `gemini-pro` | [docs](https://ai.google.dev/gemini-api/docs/models/gemini) |
|
| Google | `GEMINI_API_KEY` | `gemini-pro` | [docs](https://ai.google.dev/gemini-api/docs/models/gemini) |
|
||||||
| Anthropic | `ANTHROPIC_API_KEY` | `claude-3-haiku-20240307` | [docs](https://docs.anthropic.com/claude/docs/models-overview) |
|
| Anthropic | `ANTHROPIC_API_KEY` | `claude-3-haiku-20240307` | [docs](https://docs.anthropic.com/claude/docs/models-overview) |
|
||||||
| Replicate | `REPLICATE_API_KEY` | `meta/meta-llama-3-70b-instruct` | [docs](https://replicate.com/collections/language-models) |
|
| Replicate | `REPLICATE_API_KEY` | `replicate/meta/meta-llama-3-70b-instruct` | [docs](https://replicate.com/collections/language-models) |
|
||||||
| Ollama (local) | n/a | `llama3` | [docs](https://ollama.com/library) |
|
| Ollama (local) | n/a | `llama3` | [docs](https://ollama.com/library) |
|
||||||
| Groq | `GROQCLOUD_API_KEY` | `groq/mixtral-8x7b-32768` | [docs](https://console.groq.com/docs/models) |
|
| Groq | `GROQCLOUD_API_KEY` | `groq/mixtral-8x7b-32768` | [docs](https://console.groq.com/docs/models) |
|
||||||
| Hugging Face | `HUGGINGFACE_API_KEY` | `huggingface/mistralai/Mistral-Nemo-Instruct-2407` | [docs](https://huggingface.co/models) |
|
| Hugging Face | `HUGGINGFACE_API_KEY` | `huggingface/mistralai/Mistral-Nemo-Instruct-2407` | [docs](https://huggingface.co/models) |
|
||||||
|
@ -105,40 +105,37 @@ node main.js --profiles ./profiles/andy.json ./profiles/jill.json
|
||||||
|
|
||||||
### Model Specifications
|
### Model Specifications
|
||||||
|
|
||||||
LLM backends can be specified as simply as `"model": "gpt-3.5-turbo"`. However, for both the chat model and the embedding model, the bot profile can specify the below attributes:
|
LLM models can be specified as simply as `"model": "gpt-4o"`. However, you can specify different models for chat, coding, and embeddings.
|
||||||
|
You can pass a string or an object for these fields. A model object must specify an `api`, and optionally a `model`, `url`, and additional `params`.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"model": {
|
"model": {
|
||||||
"api": "openai",
|
"api": "openai",
|
||||||
|
"model": "gpt-4o",
|
||||||
"url": "https://api.openai.com/v1/",
|
"url": "https://api.openai.com/v1/",
|
||||||
"model": "gpt-3.5-turbo"
|
"params": {
|
||||||
|
"max_tokens": 1000,
|
||||||
|
"temperature": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"code_model": {
|
||||||
|
"api": "openai",
|
||||||
|
"model": "gpt-4",
|
||||||
|
"url": "https://api.openai.com/v1/"
|
||||||
},
|
},
|
||||||
"embedding": {
|
"embedding": {
|
||||||
"api": "openai",
|
"api": "openai",
|
||||||
"url": "https://api.openai.com/v1/",
|
"url": "https://api.openai.com/v1/",
|
||||||
"model": "text-embedding-ada-002"
|
"model": "text-embedding-ada-002"
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The model or code_model parameter accepts either a string or object. If a string, it should specify the model to be used. The api and url will be assumed. If an object, the api field must be specified. Each api has a default model and url, so those fields are optional.
|
`model` is used for chat, `code_model` is used for newAction coding, and `embedding` is used to embed text for example selection. If `code_model` is not specified, then it will use `model` for coding.
|
||||||
|
|
||||||
If the embedding field is not specified, then it will use the default embedding method for the chat model's api (Note that anthropic has no embedding model). The embedding parameter can also be a string or object. If a string, it should specify the embedding api and the default model and url will be used. If a valid embedding is not specified and cannot be assumed, then word overlap will be used to retrieve examples instead.
|
All apis have default models and urls, so those fields are optional. Note some apis have no embedding model, so they will default to word overlap to retrieve examples.
|
||||||
|
|
||||||
Thus, all the below specifications are equivalent to the above example:
|
The `params` field is optional and can be used to specify additional parameters for the model. It accepts any key-value pairs supported by the api. Is not supported for embedding models.
|
||||||
|
|
||||||
```json
|
|
||||||
"model": "gpt-3.5-turbo"
|
|
||||||
```
|
|
||||||
```json
|
|
||||||
"model": {
|
|
||||||
"api": "openai"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
```json
|
|
||||||
"model": "gpt-3.5-turbo",
|
|
||||||
"embedding": "openai"
|
|
||||||
"code_model": "gpt-3.5-turbo"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Patches
|
## Patches
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
diff --git a/node_modules/mineflayer-collectblock/lib/CollectBlock.js b/node_modules/mineflayer-collectblock/lib/CollectBlock.js
|
|
||||||
index 2c11e8c..bb49c11 100644
|
|
||||||
--- a/node_modules/mineflayer-collectblock/lib/CollectBlock.js
|
|
||||||
+++ b/node_modules/mineflayer-collectblock/lib/CollectBlock.js
|
|
||||||
@@ -77,10 +77,11 @@ function mineBlock(bot, block, options) {
|
|
||||||
}
|
|
||||||
yield bot.tool.equipForBlock(block, equipToolOptions);
|
|
||||||
// @ts-expect-error
|
|
||||||
- if (!block.canHarvest(bot.heldItem)) {
|
|
||||||
+ if (bot.heldItem !== null && !block.canHarvest(bot.heldItem.type)) {
|
|
||||||
options.targets.removeTarget(block);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
const tempEvents = new TemporarySubscriber_1.TemporarySubscriber(bot);
|
|
||||||
tempEvents.subscribeTo('itemDrop', (entity) => {
|
|
||||||
if (entity.position.distanceTo(block.position.offset(0.5, 0.5, 0.5)) <= 0.5) {
|
|
||||||
@@ -92,7 +93,7 @@ function mineBlock(bot, block, options) {
|
|
||||||
// Waiting for items to drop
|
|
||||||
yield new Promise(resolve => {
|
|
||||||
let remainingTicks = 10;
|
|
||||||
- tempEvents.subscribeTo('physicTick', () => {
|
|
||||||
+ tempEvents.subscribeTo('physicsTick', () => {
|
|
||||||
remainingTicks--;
|
|
||||||
if (remainingTicks <= 0) {
|
|
||||||
tempEvents.cleanup();
|
|
||||||
@@ -195,6 +196,8 @@ class CollectBlock {
|
|
||||||
throw (0, Util_1.error)('UnresolvedDependency', 'The mineflayer-collectblock plugin relies on the mineflayer-tool plugin to run!');
|
|
||||||
}
|
|
||||||
if (this.movements != null) {
|
|
||||||
+ this.movements.dontMineUnderFallingBlock = false;
|
|
||||||
+ this.movements.dontCreateFlow = false;
|
|
||||||
this.bot.pathfinder.setMovements(this.movements);
|
|
||||||
}
|
|
||||||
if (!optionsFull.append)
|
|
|
@ -1,5 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "gpt",
|
"name": "gpt",
|
||||||
|
|
||||||
"model": "gpt-4o"
|
"model": {
|
||||||
|
"model": "gpt-4o",
|
||||||
|
"params": {
|
||||||
|
"temperature": 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { History } from './history.js';
|
import { History } from './history.js';
|
||||||
import { Coder } from './coder.js';
|
import { Coder } from './coder.js';
|
||||||
import { Prompter } from './prompter.js';
|
import { Prompter } from '../models/prompter.js';
|
||||||
import { initModes } from './modes.js';
|
import { initModes } from './modes.js';
|
||||||
import { initBot } from '../utils/mcdata.js';
|
import { initBot } from '../utils/mcdata.js';
|
||||||
import { containsCommand, commandExists, executeCommand, truncCommandMessage, isAction, blacklistCommands } from './commands/index.js';
|
import { containsCommand, commandExists, executeCommand, truncCommandMessage, isAction, blacklistCommands } from './commands/index.js';
|
||||||
|
@ -100,11 +100,9 @@ export class Agent {
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Ensure we're not losing error details
|
// Ensure we're not losing error details
|
||||||
console.error('Agent start failed with error:', {
|
console.error('Agent start failed with error')
|
||||||
message: error.message || 'No error message',
|
console.error(error)
|
||||||
stack: error.stack || 'No stack trace',
|
|
||||||
error: error
|
|
||||||
});
|
|
||||||
throw error; // Re-throw with preserved details
|
throw error; // Re-throw with preserved details
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { strictFormat } from '../utils/text.js';
|
||||||
import { getKey } from '../utils/keys.js';
|
import { getKey } from '../utils/keys.js';
|
||||||
|
|
||||||
export class Claude {
|
export class Claude {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
let config = {};
|
let config = {};
|
||||||
if (url)
|
if (url)
|
||||||
|
@ -20,13 +21,16 @@ export class Claude {
|
||||||
let res = null;
|
let res = null;
|
||||||
try {
|
try {
|
||||||
console.log('Awaiting anthropic api response...')
|
console.log('Awaiting anthropic api response...')
|
||||||
// console.log('Messages:', messages);
|
if (!this.params.max_tokens) {
|
||||||
|
this.params.max_tokens = 4096;
|
||||||
|
}
|
||||||
const resp = await this.anthropic.messages.create({
|
const resp = await this.anthropic.messages.create({
|
||||||
model: this.model_name || "claude-3-sonnet-20240229",
|
model: this.model_name || "claude-3-sonnet-20240229",
|
||||||
system: systemMessage,
|
system: systemMessage,
|
||||||
max_tokens: 2048,
|
|
||||||
messages: messages,
|
messages: messages,
|
||||||
|
...(this.params || {})
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Received.')
|
console.log('Received.')
|
||||||
res = resp.content[0].text;
|
res = resp.content[0].text;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { getKey, hasKey } from '../utils/keys.js';
|
||||||
import { strictFormat } from '../utils/text.js';
|
import { strictFormat } from '../utils/text.js';
|
||||||
|
|
||||||
export class DeepSeek {
|
export class DeepSeek {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
let config = {};
|
let config = {};
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ export class DeepSeek {
|
||||||
model: this.model_name || "deepseek-chat",
|
model: this.model_name || "deepseek-chat",
|
||||||
messages,
|
messages,
|
||||||
stop: stop_seq,
|
stop: stop_seq,
|
||||||
|
...(this.params || {})
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = null;
|
let res = null;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { GoogleGenerativeAI } from '@google/generative-ai';
|
import { GoogleGenerativeAI } from '@google/generative-ai';
|
||||||
import { toSinglePrompt } from '../utils/text.js';
|
import { toSinglePrompt, strictFormat } from '../utils/text.js';
|
||||||
import { getKey } from '../utils/keys.js';
|
import { getKey } from '../utils/keys.js';
|
||||||
|
|
||||||
export class Gemini {
|
export class Gemini {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.safetySettings = [
|
this.safetySettings = [
|
||||||
{
|
{
|
||||||
|
@ -34,28 +35,46 @@ export class Gemini {
|
||||||
|
|
||||||
async sendRequest(turns, systemMessage) {
|
async sendRequest(turns, systemMessage) {
|
||||||
let model;
|
let model;
|
||||||
|
const modelConfig = {
|
||||||
|
model: this.model_name || "gemini-1.5-flash",
|
||||||
|
// systemInstruction does not work bc google is trash
|
||||||
|
};
|
||||||
|
|
||||||
if (this.url) {
|
if (this.url) {
|
||||||
model = this.genAI.getGenerativeModel(
|
model = this.genAI.getGenerativeModel(
|
||||||
{ model: this.model_name || "gemini-1.5-flash" },
|
modelConfig,
|
||||||
{ baseUrl: this.url },
|
{ baseUrl: this.url },
|
||||||
{ safetySettings: this.safetySettings }
|
{ safetySettings: this.safetySettings }
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
model = this.genAI.getGenerativeModel(
|
model = this.genAI.getGenerativeModel(
|
||||||
{ model: this.model_name || "gemini-1.5-flash" },
|
modelConfig,
|
||||||
{ safetySettings: this.safetySettings }
|
{ safetySettings: this.safetySettings }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const stop_seq = '***';
|
|
||||||
const prompt = toSinglePrompt(turns, systemMessage, stop_seq, 'model');
|
|
||||||
console.log('Awaiting Google API response...');
|
console.log('Awaiting Google API response...');
|
||||||
const result = await model.generateContent(prompt);
|
|
||||||
|
turns.unshift({ role: 'system', content: systemMessage });
|
||||||
|
turns = strictFormat(turns);
|
||||||
|
let contents = [];
|
||||||
|
for (let turn of turns) {
|
||||||
|
contents.push({
|
||||||
|
role: turn.role === 'assistant' ? 'model' : 'user',
|
||||||
|
parts: [{ text: turn.content }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await model.generateContent({
|
||||||
|
contents,
|
||||||
|
generationConfig: {
|
||||||
|
...(this.params || {})
|
||||||
|
}
|
||||||
|
});
|
||||||
const response = await result.response;
|
const response = await result.response;
|
||||||
const text = response.text();
|
const text = response.text();
|
||||||
console.log('Received.');
|
console.log('Received.');
|
||||||
if (!text.includes(stop_seq)) return text;
|
|
||||||
const idx = text.indexOf(stop_seq);
|
|
||||||
return text.slice(0, idx);
|
return text.slice(0, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { getKey, hasKey } from '../utils/keys.js';
|
||||||
import { strictFormat } from '../utils/text.js';
|
import { strictFormat } from '../utils/text.js';
|
||||||
|
|
||||||
export class GPT {
|
export class GPT {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
let config = {};
|
let config = {};
|
||||||
if (url)
|
if (url)
|
||||||
|
@ -25,6 +26,7 @@ export class GPT {
|
||||||
model: this.model_name || "gpt-3.5-turbo",
|
model: this.model_name || "gpt-3.5-turbo",
|
||||||
messages,
|
messages,
|
||||||
stop: stop_seq,
|
stop: stop_seq,
|
||||||
|
...(this.params || {})
|
||||||
};
|
};
|
||||||
if (this.model_name.includes('o1')) {
|
if (this.model_name.includes('o1')) {
|
||||||
pack.messages = strictFormat(messages);
|
pack.messages = strictFormat(messages);
|
||||||
|
@ -32,6 +34,7 @@ export class GPT {
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = null;
|
let res = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('Awaiting openai api response from model', this.model_name)
|
console.log('Awaiting openai api response from model', this.model_name)
|
||||||
// console.log('Messages:', messages);
|
// console.log('Messages:', messages);
|
||||||
|
|
|
@ -3,8 +3,10 @@ import { getKey } from '../utils/keys.js';
|
||||||
|
|
||||||
// xAI doesn't supply a SDK for their models, but fully supports OpenAI and Anthropic SDKs
|
// xAI doesn't supply a SDK for their models, but fully supports OpenAI and Anthropic SDKs
|
||||||
export class Grok {
|
export class Grok {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
|
this.url = url;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
let config = {};
|
let config = {};
|
||||||
if (url)
|
if (url)
|
||||||
|
@ -23,7 +25,8 @@ export class Grok {
|
||||||
const pack = {
|
const pack = {
|
||||||
model: this.model_name || "grok-beta",
|
model: this.model_name || "grok-beta",
|
||||||
messages,
|
messages,
|
||||||
stop: [stop_seq]
|
stop: [stop_seq],
|
||||||
|
...(this.params || {})
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = null;
|
let res = null;
|
||||||
|
|
|
@ -4,12 +4,13 @@ import { getKey } from '../utils/keys.js';
|
||||||
|
|
||||||
// Umbrella class for Mixtral, LLama, Gemma...
|
// Umbrella class for Mixtral, LLama, Gemma...
|
||||||
export class GroqCloudAPI {
|
export class GroqCloudAPI {
|
||||||
constructor(model_name, url, max_tokens=16384) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.max_tokens = max_tokens;
|
this.params = params;
|
||||||
// ReplicateAPI theft :3
|
// ReplicateAPI theft :3
|
||||||
if (this.url) {
|
if (this.url) {
|
||||||
|
|
||||||
console.warn("Groq Cloud has no implementation for custom URLs. Ignoring provided URL.");
|
console.warn("Groq Cloud has no implementation for custom URLs. Ignoring provided URL.");
|
||||||
}
|
}
|
||||||
this.groq = new Groq({ apiKey: getKey('GROQCLOUD_API_KEY') });
|
this.groq = new Groq({ apiKey: getKey('GROQCLOUD_API_KEY') });
|
||||||
|
@ -20,14 +21,15 @@ export class GroqCloudAPI {
|
||||||
let res = null;
|
let res = null;
|
||||||
try {
|
try {
|
||||||
console.log("Awaiting Groq response...");
|
console.log("Awaiting Groq response...");
|
||||||
|
if (!this.params.max_tokens) {
|
||||||
|
this.params.max_tokens = 16384;
|
||||||
|
}
|
||||||
let completion = await this.groq.chat.completions.create({
|
let completion = await this.groq.chat.completions.create({
|
||||||
"messages": messages,
|
"messages": messages,
|
||||||
"model": this.model_name || "mixtral-8x7b-32768",
|
"model": this.model_name || "mixtral-8x7b-32768",
|
||||||
"temperature": 0.2,
|
|
||||||
"max_tokens": this.max_tokens, // maximum token limit, differs from model to model
|
|
||||||
"top_p": 1,
|
|
||||||
"stream": true,
|
"stream": true,
|
||||||
"stop": stop_seq // "***"
|
"stop": stop_seq,
|
||||||
|
...(this.params || {})
|
||||||
});
|
});
|
||||||
|
|
||||||
let temp_res = "";
|
let temp_res = "";
|
||||||
|
|
|
@ -3,9 +3,10 @@ import {getKey} from '../utils/keys.js';
|
||||||
import {HfInference} from "@huggingface/inference";
|
import {HfInference} from "@huggingface/inference";
|
||||||
|
|
||||||
export class HuggingFace {
|
export class HuggingFace {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name.replace('huggingface/','');
|
this.model_name = model_name.replace('huggingface/','');
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
if (this.url) {
|
if (this.url) {
|
||||||
console.warn("Hugging Face doesn't support custom urls!");
|
console.warn("Hugging Face doesn't support custom urls!");
|
||||||
|
@ -25,7 +26,8 @@ export class HuggingFace {
|
||||||
console.log('Awaiting Hugging Face API response...');
|
console.log('Awaiting Hugging Face API response...');
|
||||||
for await (const chunk of this.huggingface.chatCompletionStream({
|
for await (const chunk of this.huggingface.chatCompletionStream({
|
||||||
model: model_name,
|
model: model_name,
|
||||||
messages: [{ role: "user", content: input }]
|
messages: [{ role: "user", content: input }],
|
||||||
|
...(this.params || {})
|
||||||
})) {
|
})) {
|
||||||
res += (chunk.choices[0]?.delta?.content || "");
|
res += (chunk.choices[0]?.delta?.content || "");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { strictFormat } from '../utils/text.js';
|
import { strictFormat } from '../utils/text.js';
|
||||||
|
|
||||||
export class Local {
|
export class Local {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
this.url = url || 'http://127.0.0.1:11434';
|
this.url = url || 'http://127.0.0.1:11434';
|
||||||
this.chat_endpoint = '/api/chat';
|
this.chat_endpoint = '/api/chat';
|
||||||
this.embedding_endpoint = '/api/embeddings';
|
this.embedding_endpoint = '/api/embeddings';
|
||||||
|
@ -15,7 +16,12 @@ export class Local {
|
||||||
let res = null;
|
let res = null;
|
||||||
try {
|
try {
|
||||||
console.log(`Awaiting local response... (model: ${model})`)
|
console.log(`Awaiting local response... (model: ${model})`)
|
||||||
res = await this.send(this.chat_endpoint, {model: model, messages: messages, stream: false});
|
res = await this.send(this.chat_endpoint, {
|
||||||
|
model: model,
|
||||||
|
messages: messages,
|
||||||
|
stream: false,
|
||||||
|
...(this.params || {})
|
||||||
|
});
|
||||||
if (res)
|
if (res)
|
||||||
res = res['message']['content'];
|
res = res['message']['content'];
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,13 @@ import { strictFormat } from '../utils/text.js';
|
||||||
export class Mistral {
|
export class Mistral {
|
||||||
#client;
|
#client;
|
||||||
|
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
if (typeof url === "string") {
|
if (typeof url === "string") {
|
||||||
console.warn("Mistral does not support custom URL's, ignoring!");
|
console.warn("Mistral does not support custom URL's, ignoring!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getKey("MISTRAL_API_KEY")) {
|
if (!getKey("MISTRAL_API_KEY")) {
|
||||||
|
@ -22,8 +25,6 @@ export class Mistral {
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
this.model_name = model_name;
|
|
||||||
|
|
||||||
// Prevents the following code from running when model not specified
|
// Prevents the following code from running when model not specified
|
||||||
if (typeof this.model_name === "undefined") return;
|
if (typeof this.model_name === "undefined") return;
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ export class Mistral {
|
||||||
const response = await this.#client.chat.complete({
|
const response = await this.#client.chat.complete({
|
||||||
model,
|
model,
|
||||||
messages,
|
messages,
|
||||||
|
...(this.params || {})
|
||||||
});
|
});
|
||||||
|
|
||||||
result = response.choices[0].message.content;
|
result = response.choices[0].message.content;
|
||||||
|
|
|
@ -4,9 +4,11 @@ import { strictFormat } from '../utils/text.js';
|
||||||
|
|
||||||
// llama, mistral
|
// llama, mistral
|
||||||
export class Novita {
|
export class Novita {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name.replace('novita/', '');
|
this.model_name = model_name.replace('novita/', '');
|
||||||
this.url = url || 'https://api.novita.ai/v3/openai';
|
this.url = url || 'https://api.novita.ai/v3/openai';
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
|
|
||||||
let config = {
|
let config = {
|
||||||
baseURL: this.url
|
baseURL: this.url
|
||||||
|
@ -26,6 +28,7 @@ export class Novita {
|
||||||
model: this.model_name || "meta-llama/llama-3.1-70b-instruct",
|
model: this.model_name || "meta-llama/llama-3.1-70b-instruct",
|
||||||
messages,
|
messages,
|
||||||
stop: [stop_seq],
|
stop: [stop_seq],
|
||||||
|
...(this.params || {})
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = null;
|
let res = null;
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import { readFileSync, mkdirSync, writeFileSync} from 'fs';
|
import { readFileSync, mkdirSync, writeFileSync} from 'fs';
|
||||||
import { Examples } from '../utils/examples.js';
|
import { Examples } from '../utils/examples.js';
|
||||||
import { getCommandDocs } from './commands/index.js';
|
import { getCommandDocs } from '../agent/commands/index.js';
|
||||||
import { getSkillDocs } from './library/index.js';
|
import { getSkillDocs } from '../agent/library/index.js';
|
||||||
import { stringifyTurns } from '../utils/text.js';
|
import { stringifyTurns } from '../utils/text.js';
|
||||||
import { getCommand } from './commands/index.js';
|
import { getCommand } from '../agent/commands/index.js';
|
||||||
import settings from '../../settings.js';
|
import settings from '../../settings.js';
|
||||||
|
|
||||||
import { Gemini } from '../models/gemini.js';
|
import { Gemini } from './gemini.js';
|
||||||
import { GPT } from '../models/gpt.js';
|
import { GPT } from './gpt.js';
|
||||||
import { Claude } from '../models/claude.js';
|
import { Claude } from './claude.js';
|
||||||
import { Mistral } from '../models/mistral.js';
|
import { Mistral } from './mistral.js';
|
||||||
import { ReplicateAPI } from '../models/replicate.js';
|
import { ReplicateAPI } from './replicate.js';
|
||||||
import { Local } from '../models/local.js';
|
import { Local } from './local.js';
|
||||||
import { Novita } from '../models/novita.js';
|
import { Novita } from './novita.js';
|
||||||
import { GroqCloudAPI } from '../models/groq.js';
|
import { GroqCloudAPI } from './groq.js';
|
||||||
import { HuggingFace } from '../models/huggingface.js';
|
import { HuggingFace } from './huggingface.js';
|
||||||
import { Qwen } from "../models/qwen.js";
|
import { Qwen } from "./qwen.js";
|
||||||
import { Grok } from "../models/grok.js";
|
import { Grok } from "./grok.js";
|
||||||
import { DeepSeek } from '../models/deepseek.js';
|
import { DeepSeek } from './deepseek.js';
|
||||||
|
|
||||||
export class Prompter {
|
export class Prompter {
|
||||||
constructor(agent, fp) {
|
constructor(agent, fp) {
|
||||||
|
@ -102,6 +102,8 @@ export class Prompter {
|
||||||
_selectAPI(profile) {
|
_selectAPI(profile) {
|
||||||
if (typeof profile === 'string' || profile instanceof String) {
|
if (typeof profile === 'string' || profile instanceof String) {
|
||||||
profile = {model: profile};
|
profile = {model: profile};
|
||||||
|
}
|
||||||
|
if (!profile.api) {
|
||||||
if (profile.model.includes('gemini'))
|
if (profile.model.includes('gemini'))
|
||||||
profile.api = 'google';
|
profile.api = 'google';
|
||||||
else if (profile.model.includes('gpt') || profile.model.includes('o1')|| profile.model.includes('o3'))
|
else if (profile.model.includes('gpt') || profile.model.includes('o1')|| profile.model.includes('o3'))
|
||||||
|
@ -110,7 +112,7 @@ export class Prompter {
|
||||||
profile.api = 'anthropic';
|
profile.api = 'anthropic';
|
||||||
else if (profile.model.includes('huggingface/'))
|
else if (profile.model.includes('huggingface/'))
|
||||||
profile.api = "huggingface";
|
profile.api = "huggingface";
|
||||||
else if (profile.model.includes('meta/') || profile.model.includes('replicate/'))
|
else if (profile.model.includes('replicate/'))
|
||||||
profile.api = 'replicate';
|
profile.api = 'replicate';
|
||||||
else if (profile.model.includes('mistralai/') || profile.model.includes("mistral/"))
|
else if (profile.model.includes('mistralai/') || profile.model.includes("mistral/"))
|
||||||
model_profile.api = 'mistral';
|
model_profile.api = 'mistral';
|
||||||
|
@ -133,32 +135,31 @@ export class Prompter {
|
||||||
_createModel(profile) {
|
_createModel(profile) {
|
||||||
let model = null;
|
let model = null;
|
||||||
if (profile.api === 'google')
|
if (profile.api === 'google')
|
||||||
model = new Gemini(profile.model, profile.url);
|
model = new Gemini(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'openai')
|
else if (profile.api === 'openai')
|
||||||
model = new GPT(profile.model, profile.url);
|
model = new GPT(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'anthropic')
|
else if (profile.api === 'anthropic')
|
||||||
model = new Claude(profile.model, profile.url);
|
model = new Claude(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'replicate')
|
else if (profile.api === 'replicate')
|
||||||
model = new ReplicateAPI(profile.model, profile.url);
|
model = new ReplicateAPI(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'ollama')
|
else if (profile.api === 'ollama')
|
||||||
model = new Local(profile.model, profile.url);
|
model = new Local(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'mistral')
|
else if (profile.api === 'mistral')
|
||||||
model = new Mistral(profile.model, profile.url);
|
model = new Mistral(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'groq') {
|
else if (profile.api === 'groq')
|
||||||
model = new GroqCloudAPI(profile.model.replace('groq/', '').replace('groqcloud/', ''), profile.url, max_tokens ? max_tokens : 8192);
|
model = new GroqCloudAPI(profile.model.replace('groq/', '').replace('groqcloud/', ''), profile.url, profile.params);
|
||||||
}
|
|
||||||
else if (profile.api === 'huggingface')
|
else if (profile.api === 'huggingface')
|
||||||
model = new HuggingFace(profile.model, profile.url);
|
model = new HuggingFace(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'novita')
|
else if (profile.api === 'novita')
|
||||||
model = new Novita(profile.model.replace('novita/', ''), profile.url);
|
model = new Novita(profile.model.replace('novita/', ''), profile.url, profile.params);
|
||||||
else if (profile.api === 'qwen')
|
else if (profile.api === 'qwen')
|
||||||
model = new Qwen(profile.model, profile.url);
|
model = new Qwen(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'xai')
|
else if (profile.api === 'xai')
|
||||||
model = new Grok(profile.model, profile.url);
|
model = new Grok(profile.model, profile.url, profile.params);
|
||||||
else if (profile.api === 'deepseek')
|
else if (profile.api === 'deepseek')
|
||||||
model = new DeepSeek(profile.model, profile.url);
|
model = new DeepSeek(profile.model, profile.url, profile.params);
|
||||||
else
|
else
|
||||||
throw new Error('Unknown API:', api);
|
throw new Error('Unknown API:', profile.api);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
import { getKey } from '../utils/keys.js';
|
import { getKey } from '../utils/keys.js';
|
||||||
|
|
||||||
export class Qwen {
|
export class Qwen {
|
||||||
constructor(modelName, url) {
|
constructor(model_name, url, params) {
|
||||||
this.modelName = modelName;
|
this.model_name = model_name;
|
||||||
|
this.params = params;
|
||||||
this.url = url || 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation';
|
this.url = url || 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation';
|
||||||
this.apiKey = getKey('QWEN_API_KEY');
|
this.apiKey = getKey('QWEN_API_KEY');
|
||||||
}
|
}
|
||||||
|
@ -19,7 +20,11 @@ export class Qwen {
|
||||||
const data = {
|
const data = {
|
||||||
model: this.modelName || 'qwen-plus',
|
model: this.modelName || 'qwen-plus',
|
||||||
input: { messages: [{ role: 'system', content: systemMessage }, ...turns] },
|
input: { messages: [{ role: 'system', content: systemMessage }, ...turns] },
|
||||||
parameters: { result_format: 'message', stop: stopSeq },
|
parameters: {
|
||||||
|
result_format: 'message',
|
||||||
|
stop: stopSeq,
|
||||||
|
...(this.params || {})
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add default user message if all messages are 'system' role
|
// Add default user message if all messages are 'system' role
|
||||||
|
|
|
@ -4,9 +4,10 @@ import { getKey } from '../utils/keys.js';
|
||||||
|
|
||||||
// llama, mistral
|
// llama, mistral
|
||||||
export class ReplicateAPI {
|
export class ReplicateAPI {
|
||||||
constructor(model_name, url) {
|
constructor(model_name, url, params) {
|
||||||
this.model_name = model_name;
|
this.model_name = model_name;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.params = params;
|
||||||
|
|
||||||
if (this.url) {
|
if (this.url) {
|
||||||
console.warn('Replicate API does not support custom URLs. Ignoring provided URL.');
|
console.warn('Replicate API does not support custom URLs. Ignoring provided URL.');
|
||||||
|
@ -22,7 +23,11 @@ export class ReplicateAPI {
|
||||||
const prompt = toSinglePrompt(turns, null, stop_seq);
|
const prompt = toSinglePrompt(turns, null, stop_seq);
|
||||||
let model_name = this.model_name || 'meta/meta-llama-3-70b-instruct';
|
let model_name = this.model_name || 'meta/meta-llama-3-70b-instruct';
|
||||||
|
|
||||||
const input = { prompt, system_prompt: systemMessage };
|
const input = {
|
||||||
|
prompt,
|
||||||
|
system_prompt: systemMessage,
|
||||||
|
...(this.params || {})
|
||||||
|
};
|
||||||
let res = null;
|
let res = null;
|
||||||
try {
|
try {
|
||||||
console.log('Awaiting Replicate API response...');
|
console.log('Awaiting Replicate API response...');
|
||||||
|
|
|
@ -57,11 +57,8 @@ const argv = yargs(args)
|
||||||
const agent = new Agent();
|
const agent = new Agent();
|
||||||
await agent.start(argv.profile, argv.load_memory, argv.init_message, argv.count_id, argv.task_path, argv.task_id);
|
await agent.start(argv.profile, argv.load_memory, argv.init_message, argv.count_id, argv.task_path, argv.task_id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to start agent process:', {
|
console.error('Failed to start agent process:');
|
||||||
message: error.message || 'No error message',
|
console.error(error);
|
||||||
stack: error.stack || 'No stack trace',
|
|
||||||
error: error
|
|
||||||
});
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -26,8 +26,10 @@ export function toSinglePrompt(turns, system=null, stop_seq='***', model_nicknam
|
||||||
return prompt;
|
return prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensures stricter turn order for anthropic/llama models
|
// ensures stricter turn order and roles:
|
||||||
// combines repeated messages from the same role, separates repeat assistant messages with filler user messages
|
// - system messages are treated as user messages and prefixed with SYSTEM:
|
||||||
|
// - combines repeated messages from users
|
||||||
|
// - separates repeat assistant messages with filler user messages
|
||||||
export function strictFormat(turns) {
|
export function strictFormat(turns) {
|
||||||
let prev_role = null;
|
let prev_role = null;
|
||||||
let messages = [];
|
let messages = [];
|
||||||
|
|
Loading…
Add table
Reference in a new issue