Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Mistral, use "ai" lib #321

Merged
merged 29 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
125e8fb
clean house, move to vercel's ai lib, make request tool into a zod sc…
keturiosakys Oct 15, 2024
544984d
update settings types
keturiosakys Oct 15, 2024
1788a9c
update settings page
keturiosakys Oct 15, 2024
ee7bf0f
deps
keturiosakys Oct 15, 2024
99c42a5
temp fix
keturiosakys Oct 15, 2024
c3cba9d
formatting
keturiosakys Oct 15, 2024
99f08af
renames
keturiosakys Oct 15, 2024
e7383d8
re-add fpx worker proxy type
keturiosakys Oct 15, 2024
273648c
fix ts erorrs
keturiosakys Oct 15, 2024
f636dee
remove unnecessary schemas and models
keturiosakys Oct 15, 2024
b2a02a4
fixes for openai structured outputs (they only support nullable())
keturiosakys Oct 15, 2024
54d482f
some tweaks to the settings form
keturiosakys Oct 15, 2024
173e9ed
ensure x-fpx-trace-id is filtered
keturiosakys Oct 15, 2024
8e177ea
give fixed width to the settings page so it doesn't fly off the rails
keturiosakys Oct 15, 2024
61edce9
fix type errors
keturiosakys Oct 15, 2024
69498f4
make the settings page scrollable at least
keturiosakys Oct 16, 2024
eb83488
formatting
keturiosakys Oct 16, 2024
db88b22
layout tweaks
keturiosakys Oct 16, 2024
f14df8f
formatting
keturiosakys Oct 16, 2024
5b1380b
Remove unused imports
brettimus Oct 17, 2024
468af3c
Update api/src/lib/ai/tools.ts
brettimus Oct 17, 2024
dae4169
Do not render every ai provider all the time on the settings form
brettimus Oct 17, 2024
d30679f
Modify settings layout styles to work better on md screens
brettimus Oct 17, 2024
875970e
Sort ai provider and model options in a sane way
brettimus Oct 17, 2024
162fe6e
Fix settings submission
brettimus Oct 17, 2024
eb3944e
Propagate error message from bad ai call to frontend
brettimus Oct 17, 2024
5c95c5c
Improve sorting of model names to suggest latest models
brettimus Oct 17, 2024
ca2af0f
update changelog
keturiosakys Oct 18, 2024
9ed7d96
formatting
keturiosakys Oct 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
"fpx": "bin/cli.js"
},
"dependencies": {
"@ai-sdk/anthropic": "^0.0.51",
"@ai-sdk/mistral": "^0.0.42",
"@ai-sdk/openai": "^0.0.66",
"@anthropic-ai/sdk": "^0.24.3",
"@fiberplane/fpx-types": "workspace:*",
"@hono/node-server": "^1.11.1",
Expand All @@ -48,6 +51,7 @@
"@libsql/client": "^0.6.2",
"acorn": "^8.11.3",
"acorn-walk": "^8.3.2",
"ai": "^3.4.10",
"chalk": "^5.3.0",
"dotenv": "^16.4.5",
"drizzle-kit": "^0.24.2",
Expand Down
118 changes: 0 additions & 118 deletions api/src/lib/ai/anthropic.ts

This file was deleted.

136 changes: 82 additions & 54 deletions api/src/lib/ai/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
import { createAnthropic } from "@ai-sdk/anthropic";
import { createMistral } from "@ai-sdk/mistral";
import { createOpenAI } from "@ai-sdk/openai";
import type { Settings } from "@fiberplane/fpx-types";
import { generateRequestWithAnthropic } from "./anthropic.js";
import { generateRequestWithOpenAI } from "./openai.js";
import { generateObject } from "ai";
import logger from "../../logger.js";
import { invokeRequestGenerationPrompt } from "./prompts.js";
import { requestSchema } from "./tools.js";

function configureProvider(
aiProvider: string,
providerConfig: {
apiKey: string;
baseUrl?: string | undefined;
model: string;
},
) {
if (aiProvider === "openai") {
const openai = createOpenAI({
apiKey: providerConfig.apiKey,
baseURL: providerConfig.baseUrl,
});
return openai(providerConfig.model, { structuredOutputs: true });
}
if (aiProvider === "anthropic") {
const anthropic = createAnthropic({
apiKey: providerConfig.apiKey,
baseURL: providerConfig.baseUrl,
});
return anthropic(providerConfig.model);
}

if (aiProvider === "mistral") {
const mistral = createMistral({
apiKey: providerConfig.apiKey,
baseURL: providerConfig.baseUrl,
});
return mistral(providerConfig.model);
}

throw new Error("Unknown AI provider");
}

export async function generateRequestWithAiProvider({
inferenceConfig,
Expand Down Expand Up @@ -29,67 +68,56 @@ export async function generateRequestWithAiProvider({
}[];
middlewareContext?: string;
}) {
const { aiEnabled, aiProviderConfigurations, aiProvider } = inferenceConfig;
if (!aiEnabled) {
return { data: null, error: { message: "AI is not enabled" } };
}

if (!aiProvider) {
return { data: null, error: { message: "AI provider is not set" } };
}

if (!aiProviderConfigurations || !aiProviderConfigurations[aiProvider]) {
return {
data: null,
error: { message: "AI provider is not configured properly" },
};
}

const providerConfig = aiProviderConfigurations[aiProvider];

const provider = configureProvider(aiProvider, providerConfig);

logger.debug("Generating request with AI provider", {
aiProvider,
providerConfig,
});

const {
openaiApiKey,
openaiModel,
openaiBaseUrl,
anthropicApiKey,
anthropicModel,
anthropicBaseUrl,
aiProviderType,
} = inferenceConfig;
if (aiProviderType === "openai") {
return generateRequestWithOpenAI({
apiKey: openaiApiKey ?? "",
model: openaiModel ?? "",
baseUrl: openaiBaseUrl,
persona,
method,
path,
object: generatedObject,
warnings,
usage,
} = await generateObject({
model: provider,
schema: requestSchema,
prompt: await invokeRequestGenerationPrompt({
handler,
handlerContext,
history,
openApiSpec,
middleware,
middlewareContext,
}).then(
(parsedArgs) => {
return { data: parsedArgs, error: null };
},
(error) => {
if (error instanceof Error) {
return { data: null, error: { message: error.message } };
}
return { data: null, error: { message: "Unknown error" } };
},
);
}
if (aiProviderType === "anthropic") {
return generateRequestWithAnthropic({
apiKey: anthropicApiKey ?? "",
baseUrl: anthropicBaseUrl,
model: anthropicModel ?? "",
persona,
method,
path,
handler,
handlerContext,
history,
openApiSpec,
middleware,
middlewareContext,
}).then(
(parsedArgs) => {
return { data: parsedArgs, error: null };
},
(error) => {
if (error instanceof Error) {
return { data: null, error: { message: error.message } };
}
return { data: null, error: { message: "Unknown error" } };
},
);
}
}),
});

logger.debug("Generated request, warnings, usage", {
generatedObject,
warnings,
usage,
});

return { data: null, error: { message: "Unknown AI provider" } };
return { data: generatedObject, error: null };
}
Loading
Loading