diff --git a/netlify/utils.ts b/netlify/utils.ts
index 1639249d..6bf41584 100644
--- a/netlify/utils.ts
+++ b/netlify/utils.ts
@@ -3,11 +3,16 @@ import OpenAI from "openai";
import { GoogleGenerativeAI } from "@google/generative-ai";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_KEY as string);
const model = genAI.getGenerativeModel({ model: "gemini-pro" });
+import Anthropic from "@anthropic-ai/sdk";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
+const anthropic = new Anthropic({
+ apiKey: process.env.ANTHROPIC_KEY, // defaults to process.env["ANTHROPIC_API_KEY"]
+});
+
export function errorResponse(callback, err) {
console.error(err);
@@ -24,11 +29,20 @@ const engines = {
messages: [{ role: "user", content: prompt }],
// model: "gpt-3.5-turbo",
n: 1,
- temperature: 0.7,
+ temperature: 0,
model: "gpt-4o",
// model: "gpt-4",
// model: "gpt-4-turbo-preview",
}),
+ anthropic: (prompt: string) =>
+ anthropic.messages.create({
+ // model: "claude-3-opus-20240229",
+ model: "claude-3-haiku-20240307",
+ // model: "claude-3-sonnet-20240229",
+ max_tokens: 256,
+ temperature: 0,
+ messages: [{ role: "user", content: prompt }],
+ }),
};
export const genericHandler =
@@ -54,5 +68,6 @@ export const genericHandler =
const content = prompt(promptInput);
console.log(engine, content);
const result = await engines[engine](content);
+ console.log(result);
callback(null, { statusCode: 200, body: JSON.stringify(result) });
};
diff --git a/package.json b/package.json
index bae5e9b2..276a769c 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"vitest": "^1.1.3"
},
"dependencies": {
+ "@anthropic-ai/sdk": "^0.22.0",
"@google/generative-ai": "^0.1.1",
"chroma-js": "^2.4.2",
"color-namer": "^1.4.0",
diff --git a/src/controls/Config.svelte b/src/controls/Config.svelte
index 622d8d3c..fe970de2 100644
--- a/src/controls/Config.svelte
+++ b/src/controls/Config.svelte
@@ -5,7 +5,7 @@
import Tooltip from "../components/Tooltip.svelte";
import colorStore from "../stores/color-store";
import { buttonStyle } from "../lib/styles";
- const aiModes = ["google", "openai"] as const;
+ const aiModes = ["google", "openai", "anthropic"] as const;
$: showBg = $configStore.showColorBackground;
$: showOutOfGamut = $configStore.showGamutMarkers;
diff --git a/src/lib/api-calls.ts b/src/lib/api-calls.ts
index 5db279f3..778b47e3 100644
--- a/src/lib/api-calls.ts
+++ b/src/lib/api-calls.ts
@@ -4,26 +4,30 @@ import LintWorker from "./linter-tools/lint-worker.worker?worker";
import { summarizePal } from "./utils";
import type { WorkerCommand } from "./linter-tools/worker-types";
-type Engine = "openai" | "google";
+export type Engine = "openai" | "google" | "anthropic";
type SimplePal = { background: string; colors: string[] };
const palToString = (pal: Palette) => ({
background: pal.background.toHex(),
colors: pal.colors.map((x) => x.color.toHex()),
});
+const postCreds = {
+ method: "POST",
+ mode: "cors",
+ cache: "no-cache",
+ credentials: "same-origin",
+ headers: { "Content-Type": "application/json" },
+ redirect: "follow",
+ referrerPolicy: "no-referrer",
+} as any;
+
function openAIScaffold(
api: string,
body: string,
parseAsJSON: boolean
): Promise {
return fetch(`/.netlify/functions/${api}?engine=openai`, {
- method: "POST",
- mode: "cors",
- cache: "no-cache",
- credentials: "same-origin",
- headers: { "Content-Type": "application/json" },
- redirect: "follow",
- referrerPolicy: "no-referrer",
+ ...postCreds,
body,
})
.then((response) => response.json())
@@ -36,19 +40,32 @@ function openAIScaffold(
});
}
+function anthropicScaffold(
+ api: string,
+ body: string,
+ parseAsJSON: boolean
+): Promise {
+ return fetch(`/.netlify/functions/${api}?engine=anthropic`, {
+ ...postCreds,
+ body,
+ })
+ .then((response) => response.json())
+ .then((x: any) => {
+ console.log(x);
+ return x.content
+ .map((x: any) => x?.text)
+ .filter((x: any) => x)
+ .flatMap((x: any) => (parseAsJSON ? Json.parse(x) : x));
+ });
+}
+
function googleScaffold(
api: string,
body: string,
parseAsJSON: boolean
): Promise {
return fetch(`/.netlify/functions/${api}?engine=google`, {
- method: "POST",
- mode: "cors",
- cache: "no-cache",
- credentials: "same-origin",
- headers: { "Content-Type": "application/json" },
- redirect: "follow",
- referrerPolicy: "no-referrer",
+ ...postCreds,
body,
})
.then((response) => response.json())
@@ -67,6 +84,7 @@ function googleScaffold(
const engineToScaffold = {
openai: openAIScaffold,
google: googleScaffold,
+ anthropic: anthropicScaffold,
};
// supports the add color search function
diff --git a/src/stores/config-store.ts b/src/stores/config-store.ts
index 2effb614..ad42c113 100644
--- a/src/stores/config-store.ts
+++ b/src/stores/config-store.ts
@@ -1,4 +1,5 @@
import { writable } from "svelte/store";
+import type { Engine } from "../lib/api-calls";
interface StoreData {
channelPickerSpace: "lab" | "lch" | "hsl" | "hsv" | "rgb";
@@ -8,7 +9,7 @@ interface StoreData {
compareBackgroundSpace: "lab" | "lch" | "hsl" | "hsv" | "rgb";
comparePal: number | undefined;
compareSelectedExample: number;
- engine: "openai" | "google";
+ engine: Engine;
evalDeltaDisplay: "none" | "76" | "CMC" | "2000" | "ITP" | "Jz" | "OK";
evalDisplayMode: "regular" | "compact" | "lint-customization";
exampleRoute: "svg" | "vega" | "swatches";
diff --git a/yarn.lock b/yarn.lock
index 425e7a4e..2576d6d0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -15,6 +15,20 @@
"@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"
+"@anthropic-ai/sdk@^0.22.0":
+ version "0.22.0"
+ resolved "https://registry.yarnpkg.com/@anthropic-ai/sdk/-/sdk-0.22.0.tgz#548e4218d9810fd494e595d4e57cb2d46d301a1a"
+ integrity sha512-dv4BCC6FZJw3w66WNLsHlUFjhu19fS1L/5jMPApwhZLa/Oy1j0A2i3RypmDtHEPp4Wwg3aZkSHksp7VzYWjzmw==
+ dependencies:
+ "@types/node" "^18.11.18"
+ "@types/node-fetch" "^2.6.4"
+ abort-controller "^3.0.0"
+ agentkeepalive "^4.2.1"
+ form-data-encoder "1.7.2"
+ formdata-node "^4.3.2"
+ node-fetch "^2.6.7"
+ web-streams-polyfill "^3.2.1"
+
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0":
version "7.23.5"
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz"