From 8b4ea79b9a57e08a48e79dcd1a781cac335f7fae Mon Sep 17 00:00:00 2001 From: Sam Kemp Date: Mon, 27 May 2024 12:36:29 +0100 Subject: [PATCH 1/4] Switched to config.json instead of environment variable --- .gitignore | 3 ++- config.example.json | 7 +++++++ src/models/claude.js | 7 ++++--- src/models/gemini.js | 7 ++++--- src/models/gpt.js | 12 ++++++------ src/models/replicate.js | 7 ++++--- 6 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 config.example.json diff --git a/.gitignore b/.gitignore index 61f81fd..6e6fd2d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules/ package-lock.json scratch.js bots/**/action-code/** -bots/**/ \ No newline at end of file +bots/**/ +config.json \ No newline at end of file diff --git a/config.example.json b/config.example.json new file mode 100644 index 0000000..8e4037c --- /dev/null +++ b/config.example.json @@ -0,0 +1,7 @@ +{ + "OPENAI_API_KEY": "", + "OPENAI_ORG_ID": "", + "GEMINI_API_KEY": "", + "ANTHROPIC_API_KEY": "", + "REPLICATE_API_KEY": "" +} \ No newline at end of file diff --git a/src/models/claude.js b/src/models/claude.js index e189a38..754cd7a 100644 --- a/src/models/claude.js +++ b/src/models/claude.js @@ -1,4 +1,5 @@ import Anthropic from '@anthropic-ai/sdk'; +import configJson from "../../config.json" assert { type: "json" }; export class Claude { @@ -8,10 +9,10 @@ export class Claude { let config = {}; if (url) config.baseURL = url; - if (process.env.ANTHROPIC_API_KEY) - config.apiKey = process.env["ANTHROPIC_API_KEY"]; + if (configJson.ANTHROPIC_API_KEY) + config.apiKey = configJson.ANTHROPIC_API_KEY; else - throw new Error('Anthropic API key missing! Make sure you set your ANTHROPIC_API_KEY environment variable.'); + throw new Error('Anthropic API key missing! Make sure you set your ANTHROPIC_API_KEY in your config.json.'); this.anthropic = new Anthropic(config); } diff --git a/src/models/gemini.js b/src/models/gemini.js index 61f4f1a..b0d315b 100644 --- a/src/models/gemini.js +++ b/src/models/gemini.js @@ -1,15 +1,16 @@ import { GoogleGenerativeAI } from '@google/generative-ai'; import { toSinglePrompt } from '../utils/text.js'; +import configJson from "../../config.json" assert { type: "json" }; export class Gemini { constructor(model_name, url) { this.model_name = model_name; this.url = url; - if (!process.env.GEMINI_API_KEY) { - throw new Error('Gemini API key missing! Make sure you set your GEMINI_API_KEY environment variable.'); + if (!configJson.GEMINI_API_KEY) { + throw new Error('Gemini API key missing! Make sure you set your GEMINI_API_KEY in your config.json.'); } - this.genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); + this.genAI = new GoogleGenerativeAI(configJson.GEMINI_API_KEY); } async sendRequest(turns, systemMessage) { diff --git a/src/models/gpt.js b/src/models/gpt.js index 0889c31..9f674b9 100644 --- a/src/models/gpt.js +++ b/src/models/gpt.js @@ -1,5 +1,5 @@ import OpenAIApi from 'openai'; - +import configJson from "../../config.json" assert { type: "json" }; export class GPT { constructor(model_name, url) { @@ -8,12 +8,12 @@ export class GPT { let config = {}; if (url) config.baseURL = url; - if (process.env.OPENAI_ORG_ID) - config.organization = process.env.OPENAI_ORG_ID - if (process.env.OPENAI_API_KEY) - config.apiKey = process.env.OPENAI_API_KEY + if (configJson.OPENAI_ORG_ID) + config.organization = configJson.OPENAI_ORG_ID; + if (configJson.OPENAI_API_KEY) + config.apiKey = configJson.OPENAI_API_KEY; else - throw new Error('OpenAI API key missing! Make sure you set your OPENAI_API_KEY environment variable.'); + throw new Error('OpenAI API key missing! Make sure you set your OPENAI_API_KEY in your config.json.'); this.openai = new OpenAIApi(config); } diff --git a/src/models/replicate.js b/src/models/replicate.js index ea5a4a9..1059f0f 100644 --- a/src/models/replicate.js +++ b/src/models/replicate.js @@ -1,5 +1,6 @@ import Replicate from 'replicate'; import { toSinglePrompt } from '../utils/text.js'; +import configJson from "../../config.json" assert { type: "json" }; // llama, mistral export class ReplicateAPI { @@ -11,12 +12,12 @@ export class ReplicateAPI { console.warn('Replicate API does not support custom URLs. Ignoring provided URL.'); } - if (!process.env.REPLICATE_API_KEY) { - throw new Error('Replicate API key missing! Make sure you set your REPLICATE_API_KEY environment variable.'); + if (!configJson.REPLICATE_API_KEY) { + throw new Error('Replicate API key missing! Make sure you set your REPLICATE_API_KEY in your config.json.'); } this.replicate = new Replicate({ - auth: process.env.REPLICATE_API_KEY, + auth: configJson.REPLICATE_API_KEY, }); } From b17f4806a30b95799b31e245cccca04ed41b2dcc Mon Sep 17 00:00:00 2001 From: Sam Kemp Date: Mon, 27 May 2024 12:47:12 +0100 Subject: [PATCH 2/4] Updated README.md --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3566f6a..6dd9c53 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,8 @@ This project allows an AI model to write/execute code on your computer that may ## Installation -Add the environment variable for the model you want to use: - -| API | Env Variable | Example Model name | Docs | +Rename `config.example.json` to `config.json` and fill in the desired API keys +| API | Config Variable | Example Model name | Docs | |------|------|------|------| | OpenAI | `OPENAI_API_KEY` | `gpt-3.5-turbo` | [docs](https://platform.openai.com/docs/models) | (optionally add `OPENAI_ORG_ID`) | Google | `GEMINI_API_KEY` | `gemini-pro` | [docs](https://ai.google.dev/gemini-api/docs/models/gemini) | @@ -24,8 +23,6 @@ Add the environment variable for the model you want to use: | Replicate | `REPLICATE_API_KEY` | `meta/meta-llama-3-70b-instruct` | [docs](https://replicate.com/collections/language-models) | | Ollama (local) | n/a | `llama3` | [docs](https://ollama.com/library) | -⭐[How do I add the API key as an environment variable?](https://phoenixnap.com/kb/windows-set-environment-variable)⭐ - If you use Ollama, to install the models used by default (generation and embedding), execute the following terminal command: `ollama pull llama3 && ollama pull nomic-embed-text` From fe621ebcf8d1b62b4e871adb2e95409456fb3dc9 Mon Sep 17 00:00:00 2001 From: Sam Kemp Date: Thu, 30 May 2024 17:30:34 +0100 Subject: [PATCH 3/4] Renamed config.json to keys.json and added check for env var if keys.json isn't found --- .gitignore | 2 +- README.md | 2 +- config.example.json => keys.example.json | 0 src/models/claude.js | 6 ++++-- src/models/gemini.js | 12 +++++++----- src/models/gpt.js | 12 +++++++++--- src/models/replicate.js | 19 +++++++++++-------- 7 files changed, 33 insertions(+), 20 deletions(-) rename config.example.json => keys.example.json (100%) diff --git a/.gitignore b/.gitignore index 6e6fd2d..a139094 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ package-lock.json scratch.js bots/**/action-code/** bots/**/ -config.json \ No newline at end of file +keys.json \ No newline at end of file diff --git a/README.md b/README.md index 6dd9c53..a7f1735 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This project allows an AI model to write/execute code on your computer that may ## Installation -Rename `config.example.json` to `config.json` and fill in the desired API keys +Rename `keys.example.json` to `keys.json` and fill in the desired API keys | API | Config Variable | Example Model name | Docs | |------|------|------|------| | OpenAI | `OPENAI_API_KEY` | `gpt-3.5-turbo` | [docs](https://platform.openai.com/docs/models) | (optionally add `OPENAI_ORG_ID`) diff --git a/config.example.json b/keys.example.json similarity index 100% rename from config.example.json rename to keys.example.json diff --git a/src/models/claude.js b/src/models/claude.js index 754cd7a..19fe053 100644 --- a/src/models/claude.js +++ b/src/models/claude.js @@ -1,5 +1,5 @@ import Anthropic from '@anthropic-ai/sdk'; -import configJson from "../../config.json" assert { type: "json" }; +import configJson from "../../keys.json" assert { type: "json" }; export class Claude { @@ -11,8 +11,10 @@ export class Claude { config.baseURL = url; if (configJson.ANTHROPIC_API_KEY) config.apiKey = configJson.ANTHROPIC_API_KEY; + else if (process.env.ANTHROPIC_API_KEY) + config.apiKey = process.env.ANTHROPIC_API_KEY; else - throw new Error('Anthropic API key missing! Make sure you set your ANTHROPIC_API_KEY in your config.json.'); + throw new Error('Anthropic API key missing! Make sure you set your ANTHROPIC_API_KEY in your keys.json.'); this.anthropic = new Anthropic(config); } diff --git a/src/models/gemini.js b/src/models/gemini.js index b0d315b..8273b96 100644 --- a/src/models/gemini.js +++ b/src/models/gemini.js @@ -1,16 +1,18 @@ import { GoogleGenerativeAI } from '@google/generative-ai'; import { toSinglePrompt } from '../utils/text.js'; -import configJson from "../../config.json" assert { type: "json" }; +import configJson from "../../keys.json" assert { type: "json" }; export class Gemini { constructor(model_name, url) { this.model_name = model_name; this.url = url; - if (!configJson.GEMINI_API_KEY) { - throw new Error('Gemini API key missing! Make sure you set your GEMINI_API_KEY in your config.json.'); - } - this.genAI = new GoogleGenerativeAI(configJson.GEMINI_API_KEY); + if (configJson.GEMINI_API_KEY) + this.genAI = new GoogleGenerativeAI(configJson.GEMINI_API_KEY); + else if (process.env.GEMINI_API_KEY) + this.genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); + else + throw new Error('Gemini API key missing! Make sure you set your GEMINI_API_KEY in your keys.json.'); } async sendRequest(turns, systemMessage) { diff --git a/src/models/gpt.js b/src/models/gpt.js index 9f674b9..0f88ec5 100644 --- a/src/models/gpt.js +++ b/src/models/gpt.js @@ -1,5 +1,5 @@ import OpenAIApi from 'openai'; -import configJson from "../../config.json" assert { type: "json" }; +import configJson from "../../keys.json" assert { type: "json" }; export class GPT { constructor(model_name, url) { @@ -8,12 +8,18 @@ export class GPT { let config = {}; if (url) config.baseURL = url; + if (configJson.OPENAI_ORG_ID) - config.organization = configJson.OPENAI_ORG_ID; + config.apiKey = configJson.OPENAI_ORG_ID; + else if (process.env.OPENAI_ORG_ID) + config.apiKey = process.env.OPENAI_ORG_ID; + if (configJson.OPENAI_API_KEY) config.apiKey = configJson.OPENAI_API_KEY; + else if (process.env.OPENAI_API_KEY) + config.apiKey = process.env.OPENAI_API_KEY; else - throw new Error('OpenAI API key missing! Make sure you set your OPENAI_API_KEY in your config.json.'); + throw new Error('OpenAI API key missing! Make sure you set your OPENAI_API_KEY in your keys.json.'); this.openai = new OpenAIApi(config); } diff --git a/src/models/replicate.js b/src/models/replicate.js index 1059f0f..2ec30ba 100644 --- a/src/models/replicate.js +++ b/src/models/replicate.js @@ -1,6 +1,6 @@ import Replicate from 'replicate'; import { toSinglePrompt } from '../utils/text.js'; -import configJson from "../../config.json" assert { type: "json" }; +import configJson from "../../keys.json" assert { type: "json" }; // llama, mistral export class ReplicateAPI { @@ -12,13 +12,16 @@ export class ReplicateAPI { console.warn('Replicate API does not support custom URLs. Ignoring provided URL.'); } - if (!configJson.REPLICATE_API_KEY) { - throw new Error('Replicate API key missing! Make sure you set your REPLICATE_API_KEY in your config.json.'); - } - - this.replicate = new Replicate({ - auth: configJson.REPLICATE_API_KEY, - }); + if (configJson.REPLICATE_API_KEY) + this.replicate = new Replicate({ + auth: configJson.REPLICATE_API_KEY, + }); + else if (process.env.REPLICATE_API_KEY) + this.replicate = new Replicate({ + auth: process.env.REPLICATE_API_KEY, + }); + else + throw new Error('Replicate API key missing! Make sure you set your REPLICATE_API_KEY in your keys.json.'); } async sendRequest(turns, systemMessage) { From 24a63703329ff611100c2742c13408514bd5f37e Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 30 May 2024 18:00:48 -0500 Subject: [PATCH 4/4] refactored into key reader --- README.md | 2 +- src/models/claude.js | 11 +++-------- src/models/gemini.js | 9 ++------- src/models/gpt.js | 15 ++++----------- src/models/replicate.js | 15 ++++----------- src/utils/keys.js | 24 ++++++++++++++++++++++++ 6 files changed, 38 insertions(+), 38 deletions(-) create mode 100644 src/utils/keys.js diff --git a/README.md b/README.md index 4ac5be3..79a8616 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ This project allows an AI model to write/execute code on your computer that may ## Installation -Rename `keys.example.json` to `keys.json` and fill in the desired API keys +Rename `keys.example.json` to `keys.json` and fill in your API keys, and you can set the desired model in `andy.json` or other profiles. | API | Config Variable | Example Model name | Docs | |------|------|------|------| | OpenAI | `OPENAI_API_KEY` | `gpt-3.5-turbo` | [docs](https://platform.openai.com/docs/models) | (optionally add `OPENAI_ORG_ID`) diff --git a/src/models/claude.js b/src/models/claude.js index 19fe053..46691d5 100644 --- a/src/models/claude.js +++ b/src/models/claude.js @@ -1,6 +1,5 @@ import Anthropic from '@anthropic-ai/sdk'; -import configJson from "../../keys.json" assert { type: "json" }; - +import { getKey } from '../utils/keys.js'; export class Claude { constructor(model_name, url) { @@ -9,12 +8,8 @@ export class Claude { let config = {}; if (url) config.baseURL = url; - if (configJson.ANTHROPIC_API_KEY) - config.apiKey = configJson.ANTHROPIC_API_KEY; - else if (process.env.ANTHROPIC_API_KEY) - config.apiKey = process.env.ANTHROPIC_API_KEY; - else - throw new Error('Anthropic API key missing! Make sure you set your ANTHROPIC_API_KEY in your keys.json.'); + + config.apiKey = getKey('ANTHROPIC_API_KEY'); this.anthropic = new Anthropic(config); } diff --git a/src/models/gemini.js b/src/models/gemini.js index 8273b96..7d652d5 100644 --- a/src/models/gemini.js +++ b/src/models/gemini.js @@ -1,18 +1,13 @@ import { GoogleGenerativeAI } from '@google/generative-ai'; import { toSinglePrompt } from '../utils/text.js'; -import configJson from "../../keys.json" assert { type: "json" }; +import { getKey } from '../utils/keys.js'; export class Gemini { constructor(model_name, url) { this.model_name = model_name; this.url = url; - if (configJson.GEMINI_API_KEY) - this.genAI = new GoogleGenerativeAI(configJson.GEMINI_API_KEY); - else if (process.env.GEMINI_API_KEY) - this.genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); - else - throw new Error('Gemini API key missing! Make sure you set your GEMINI_API_KEY in your keys.json.'); + this.genAI = new GoogleGenerativeAI(getKey('GEMINI_API_KEY')); } async sendRequest(turns, systemMessage) { diff --git a/src/models/gpt.js b/src/models/gpt.js index 0f88ec5..061596b 100644 --- a/src/models/gpt.js +++ b/src/models/gpt.js @@ -1,5 +1,5 @@ import OpenAIApi from 'openai'; -import configJson from "../../keys.json" assert { type: "json" }; +import { getKey, hasKey } from '../utils/keys.js'; export class GPT { constructor(model_name, url) { @@ -9,17 +9,10 @@ export class GPT { if (url) config.baseURL = url; - if (configJson.OPENAI_ORG_ID) - config.apiKey = configJson.OPENAI_ORG_ID; - else if (process.env.OPENAI_ORG_ID) - config.apiKey = process.env.OPENAI_ORG_ID; + if (hasKey('OPENAI_ORG_ID')) + config.organization = getKey('OPENAI_ORG_ID'); - if (configJson.OPENAI_API_KEY) - config.apiKey = configJson.OPENAI_API_KEY; - else if (process.env.OPENAI_API_KEY) - config.apiKey = process.env.OPENAI_API_KEY; - else - throw new Error('OpenAI API key missing! Make sure you set your OPENAI_API_KEY in your keys.json.'); + config.apiKey = getKey('OPENAI_API_KEY'); this.openai = new OpenAIApi(config); } diff --git a/src/models/replicate.js b/src/models/replicate.js index 2ec30ba..e0c7d6c 100644 --- a/src/models/replicate.js +++ b/src/models/replicate.js @@ -1,6 +1,6 @@ import Replicate from 'replicate'; import { toSinglePrompt } from '../utils/text.js'; -import configJson from "../../keys.json" assert { type: "json" }; +import { getKey } from '../utils/keys.js'; // llama, mistral export class ReplicateAPI { @@ -12,16 +12,9 @@ export class ReplicateAPI { console.warn('Replicate API does not support custom URLs. Ignoring provided URL.'); } - if (configJson.REPLICATE_API_KEY) - this.replicate = new Replicate({ - auth: configJson.REPLICATE_API_KEY, - }); - else if (process.env.REPLICATE_API_KEY) - this.replicate = new Replicate({ - auth: process.env.REPLICATE_API_KEY, - }); - else - throw new Error('Replicate API key missing! Make sure you set your REPLICATE_API_KEY in your keys.json.'); + this.replicate = new Replicate({ + auth: getKey('REPLICATE_API_KEY'), + }); } async sendRequest(turns, systemMessage) { diff --git a/src/utils/keys.js b/src/utils/keys.js new file mode 100644 index 0000000..745ae6c --- /dev/null +++ b/src/utils/keys.js @@ -0,0 +1,24 @@ +import { readFileSync } from 'fs'; + +let keys = {}; +try { + const data = readFileSync('./keys.json', 'utf8'); + keys = JSON.parse(data); +} catch (err) { + console.warn('keys.json not found. Defaulting to environment variables.'); // still works with local models +} + +export function getKey(name) { + let key = keys[name]; + if (!key) { + key = process.env[name]; + } + if (!key) { + throw new Error(`API key "${name}" not found in keys.json or environment variables!`); + } + return keys[name]; +} + +export function hasKey(name) { + return keys[name] || process.env[name]; +}