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

feat: gemini model #194

Merged
merged 1 commit into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ KINDE_POST_LOGOUT_REDIRECT_URL=http://localhost:3000
KINDE_POST_LOGIN_REDIRECT_URL=http://localhost:3000/dashboard
CONVEX_DEPLOYMENT=dev:perfect-panther-605
NEXT_PUBLIC_CONVEX_URL=https://perfect-panther-605.convex.cloud
NEXT_PUBLIC_GEMINI_API_KEY=your-gemini-api-key
#use these variables only ;)
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@formspree/react": "^2.5.1",
"@hookform/resolvers": "^3.4.0",
"@kinde-oss/kinde-auth-nextjs": "^2.2.6",
"@langchain/google-genai": "^0.0.16",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
Expand All @@ -42,6 +43,7 @@
"embla-carousel-react": "^8.0.4",
"express": "^4.19.2",
"framer-motion": "^11.1.9",
"langchain": "^0.2.4",
"lucide-react": "^0.378.0",
"moment": "^2.30.1",
"next": "^14.2.3",
Expand Down
102 changes: 65 additions & 37 deletions src/components/shared/AiModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,24 @@ import {
FormLabel,
FormMessage,
} from "@/components/ui/form";
import runChat from "@/config/gemini";
import PromptLoader from "./PromptLoader";

const formSchema = z.object({
prompt: z
.string()
.min(100, {
message: "Description should be atleast 100 characters long",
})
// .min(100, {
// message: "Description should be atleast 100 characters long",
// })
.max(550),
});

export function GenAIModal() {
const [docsCheck, setDocsChecked] = useState<boolean>(false);
const [flowchartCheck, setFlowchartChecked] = useState<boolean>(false);
const [validation, setValidation] = useState("");
const [loading, setLoading] = useState(false);
const [isDialogOpen, setIsDialogOpen] = useState(false);

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
Expand All @@ -46,16 +51,30 @@ export function GenAIModal() {
},
});

function onSubmit(values: z.infer<typeof formSchema>) {
async function onSubmit(values: z.infer<typeof formSchema>) {
// Do something with the form values.
// ✅ This will be type-safe and validated.
console.log(values);
try {
setLoading(true);
if (!docsCheck && !flowchartCheck) setValidation("Select atleast one!");
else {
const res = await runChat(values.prompt, docsCheck, flowchartCheck);
console.log(res);
if(res){
setLoading(false);
setIsDialogOpen(false);
}
}
} catch (err) {
console.log(err);
}
}

return (
<Dialog>
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<DialogTrigger asChild>
<Button className="flex gap-2">
<Button className="flex gap-2" onClick={() => setIsDialogOpen(true)}>
<WandSparkles className="w-4 h-4" />
<p className="hidden sm:inline">Generate AI</p>
</Button>
Expand All @@ -82,49 +101,58 @@ export function GenAIModal() {
/>
</FormControl>
<FormDescription className=" text-xs font-semibold text-red-500">
<span className="font-bold">Note : </span>
Give detailed description of your problem statement
<span className="font-bold">Note : </span>
Give detailed description of your problem statement
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<div className="flex items-center space-x-2">
<Checkbox
checked={docsCheck}
onCheckedChange={() => setDocsChecked(!docsCheck)}
id="docs"
/>
<label
htmlFor="docs"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Generate Documentation
</label>
</div>
<div className="flex flex-col gap-4">
<div className="flex items-center space-x-2">
<Checkbox
checked={docsCheck}
onCheckedChange={() => setDocsChecked(!docsCheck)}
id="docs"
/>
<label
htmlFor="docs"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Generate Documentation
</label>
</div>

<div className="flex items-center space-x-2">
<Checkbox
checked={flowchartCheck}
onCheckedChange={() => setFlowchartChecked(!flowchartCheck)}
id="flowchart"
/>
<label
htmlFor="flowchart"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Generate Flowchart
</label>
</div>

<div className="flex items-center space-x-2">
<Checkbox
checked={flowchartCheck}
onCheckedChange={() => setFlowchartChecked(!flowchartCheck)}
id="flowchart"
/>
<label
htmlFor="flowchart"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Generate Flowchart
</label>
<p className="text-xs font-semibold text-red-500">{validation}</p>
</div>

<DialogFooter>
<Button className="flex gap-2" type="submit">
<p>
Generate
</p>
<Send className="w-[14px] h-[14px]" /> </Button>
<p>Generate</p>
<Send className="w-[14px] h-[14px]" />{" "}
</Button>
</DialogFooter>
</form>
</Form>
{loading && (
<div className="backdrop-blur-sm absolute flex item-center justify-center w-full h-full top-0 left-0">
<PromptLoader />
</div>
)}
</DialogContent>
</Dialog>
);
Expand Down
48 changes: 48 additions & 0 deletions src/components/shared/PromptLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { motion } from 'framer-motion'

export default function PromptLoader() {
return (
<div className="flex items-center justify-center">
<div className="flex space-x-2">
<motion.div
className="h-3 w-3 rounded-full bg-red-500"
animate={{
scale: [1, 1.5, 1],
opacity: [0.5, 1, 0.5],
}}
transition={{
duration: 1,
ease: 'easeInOut',
repeat: Infinity,
}}
/>
<motion.div
className="h-3 w-3 rounded-full bg-red-500"
animate={{
scale: [1, 1.5, 1],
opacity: [0.5, 1, 0.5],
}}
transition={{
duration: 1,
ease: 'easeInOut',
repeat: Infinity,
delay: 0.3,
}}
/>
<motion.div
className="h-3 w-3 rounded-full bg-red-500"
animate={{
scale: [1, 1.5, 1],
opacity: [0.5, 1, 0.5],
}}
transition={{
duration: 1,
ease: 'easeInOut',
repeat: Infinity,
delay: 0.6,
}}
/>
</div>
</div>
)
}
58 changes: 58 additions & 0 deletions src/config/gemini.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { GoogleGenerativeAI } from "@google/generative-ai";

const MODEL_NAME = "gemini-1.0-pro";
const API_KEY = process.env.NEXT_PUBLIC_GEMINI_API_KEY;

async function runChat(
prompt: string,
generateDocs: boolean,
generateFlowchart: boolean
) {
if (!API_KEY || API_KEY === "your-gemini-api-key")
throw new Error("Invalid Api Key!");

const genAI = new GoogleGenerativeAI(API_KEY);
const model = genAI.getGenerativeModel({ model: MODEL_NAME });

model.generationConfig = {
temperature: 0.9,
topK: 1,
topP: 1,
};

const chat = model.startChat({
history: [
{
role: "user",
parts: [
{
text: `You are expert in generating documentation and flowcharts. While generating documentation add detailed working of given prompt and generate the flowcharts in mermaid code format. Generate the flowchart in the mermaid code format.`,
},
],
},
{
role: "model",
parts: [{ text: "How can I help you ?" }],
},
],
});

let newPrompt;

if (generateDocs && generateFlowchart) {
newPrompt = `Generate documentation as well as flowchart for following problem statement. Problem Statement : ${prompt}`;
} else if (generateDocs) {
newPrompt = `Generate documentation for following problem statement. Problem Statement : ${prompt}`;
} else if (generateFlowchart) {
newPrompt = `Generate flowchart for following problem statement. Problem Statement : ${prompt}`;
}

if(!generateDocs && !generateFlowchart) throw new Error("No options selected!");

const result = await chat.sendMessage(newPrompt!);
const response = result.response;
console.log(response.text());
return response.text();
}

export default runChat;
Loading