feat: add AI assistant to dokploy

This commit is contained in:
Andrey Kucherenko
2025-01-10 08:18:43 +01:00
parent 123605dc0d
commit b58b6636e3
25 changed files with 6842 additions and 50 deletions

View File

@@ -0,0 +1,104 @@
import { db } from "@dokploy/server/db";
import { ai } from "@dokploy/server/db/schema";
import { selectAIProvider } from "@dokploy/server/utils/ai/select-ai-provider";
import { TRPCError } from "@trpc/server";
import { generateObject } from "ai";
import { eq } from "drizzle-orm";
import { z } from "zod";
export const getAiSettingsByAuthId = async (authId: string) => {
const aiSettings = await db.query.ai.findFirst({
where: eq(ai.authId, authId),
});
if (!aiSettings) {
throw new TRPCError({
code: "NOT_FOUND",
message: "AI settings not found for the user",
});
}
return aiSettings;
};
export const saveAiSettings = async (authId: string, settings: any) => {
return db
.insert(ai)
.values({
authId,
...settings,
})
.onConflictDoUpdate({
target: ai.authId,
set: {
...settings,
},
});
};
export const suggestVariants = async (authId: string, input: string) => {
const aiSettings = await getAiSettingsByAuthId(authId);
if (!aiSettings || !aiSettings.isEnabled) {
throw new TRPCError({
code: "NOT_FOUND",
message: "AI features are not enabled",
});
}
const provider = selectAIProvider(aiSettings);
const model = provider(aiSettings.model);
const { object } = await generateObject({
model,
output: "array",
schema: z.object({
id: z.string(),
name: z.string(),
shortDescription: z.string(),
description: z.string(),
}),
prompt: `
Act as advanced DevOps engineer and generate a list of open source projects what can cover users needs(up to 3 items), the suggestion
should include id, name, shortDescription, and description. Use slug of title for id. The description should be in markdown format with full description of suggested stack. The shortDescription should be in plain text and have short information about used technologies.
User wants to create a new project with the following details, it should be installable in docker and can be docker compose generated for it:
${input}
`,
});
if (object?.length) {
const result = [];
for (const suggestion of object) {
const { object: docker } = await generateObject({
model,
output: "object",
schema: z.object({
dockerCompose: z.string(),
envVariables: z.array(
z.object({
name: z.string(),
value: z.string(),
}),
),
}),
prompt: `
Act as advanced DevOps engineer and generate docker compose with environment variables needed to install the following project,
use placeholder like \${VARIABLE_NAME-default} for generated variables in the docker compose. Use complex values for passwords/secrets variables.
Don\'t set container_name field in services. Don\'t set version field in the docker compose.
Project details:
${suggestion?.description}
`,
});
if (!!docker && !!docker.dockerCompose) {
result.push({
...suggestion,
...docker,
});
}
}
return result;
}
throw new TRPCError({
code: "NOT_FOUND",
message: "No suggestions found",
});
};