diff --git a/.gitignore b/.gitignore index 9d80c04..a2aee7e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ package-lock.json code_records/ scratch.js bots/**/action-code/** -bots/**/ \ No newline at end of file +bots/**/ +keys.json \ No newline at end of file diff --git a/README.md b/README.md index fc74ed0..79a8616 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 `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`) | 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` diff --git a/keys.example.json b/keys.example.json new file mode 100644 index 0000000..8e4037c --- /dev/null +++ b/keys.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..46691d5 100644 --- a/src/models/claude.js +++ b/src/models/claude.js @@ -1,5 +1,5 @@ import Anthropic from '@anthropic-ai/sdk'; - +import { getKey } from '../utils/keys.js'; export class Claude { constructor(model_name, url) { @@ -8,10 +8,8 @@ export class Claude { let config = {}; if (url) config.baseURL = url; - 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 environment variable.'); + + config.apiKey = getKey('ANTHROPIC_API_KEY'); this.anthropic = new Anthropic(config); } diff --git a/src/models/gemini.js b/src/models/gemini.js index 61f4f1a..7d652d5 100644 --- a/src/models/gemini.js +++ b/src/models/gemini.js @@ -1,15 +1,13 @@ import { GoogleGenerativeAI } from '@google/generative-ai'; import { toSinglePrompt } from '../utils/text.js'; +import { getKey } from '../utils/keys.js'; 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.'); - } - this.genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); + 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 0889c31..061596b 100644 --- a/src/models/gpt.js +++ b/src/models/gpt.js @@ -1,5 +1,5 @@ import OpenAIApi from 'openai'; - +import { getKey, hasKey } from '../utils/keys.js'; export class GPT { constructor(model_name, url) { @@ -8,12 +8,11 @@ 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 - else - throw new Error('OpenAI API key missing! Make sure you set your OPENAI_API_KEY environment variable.'); + + if (hasKey('OPENAI_ORG_ID')) + config.organization = getKey('OPENAI_ORG_ID'); + + config.apiKey = getKey('OPENAI_API_KEY'); this.openai = new OpenAIApi(config); } diff --git a/src/models/replicate.js b/src/models/replicate.js index ea5a4a9..e0c7d6c 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 { getKey } from '../utils/keys.js'; // llama, mistral export class ReplicateAPI { @@ -11,12 +12,8 @@ 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.'); - } - this.replicate = new Replicate({ - auth: process.env.REPLICATE_API_KEY, + auth: getKey('REPLICATE_API_KEY'), }); } 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]; +}