Gemini Integration
This commit is contained in:
parent
89873a990f
commit
4ce7c42753
2
.env
Normal file
2
.env
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Google Gemini API Key
|
||||||
|
NEXT_PUBLIC_GEMINI_API_KEY=AIzaSyAK8AyA8JYTprpqIif4qBiPql84Uh0VFh4
|
@ -5,6 +5,7 @@ import TypingAnimation from './TypingAnimation';
|
|||||||
import { getPromptContent } from '../utils/promptContent';
|
import { getPromptContent } from '../utils/promptContent';
|
||||||
import { Plus, Send, Upload } from 'lucide-react';
|
import { Plus, Send, Upload } from 'lucide-react';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
||||||
|
import { generateResponse } from '@/services/geminiService';
|
||||||
|
|
||||||
interface ChatInterfaceProps {
|
interface ChatInterfaceProps {
|
||||||
onPromptSelect: (prompt: string, content: any) => void;
|
onPromptSelect: (prompt: string, content: any) => void;
|
||||||
@ -92,13 +93,10 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({ onPromptSelect, isExpande
|
|||||||
}, 1000); // "Thinking..." duration
|
}, 1000); // "Thinking..." duration
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSendMessage = () => {
|
const handleSendMessage = async () => {
|
||||||
if (!inputValue.trim()) return;
|
if (!inputValue.trim()) return;
|
||||||
|
|
||||||
const userMessage = {
|
const userMessage = { text: inputValue, isUser: true };
|
||||||
text: inputValue,
|
|
||||||
isUser: true,
|
|
||||||
};
|
|
||||||
setMessages(prev => [...prev, userMessage]);
|
setMessages(prev => [...prev, userMessage]);
|
||||||
|
|
||||||
const matched = promptPatterns.find(({ pattern }) => pattern.test(inputValue));
|
const matched = promptPatterns.find(({ pattern }) => pattern.test(inputValue));
|
||||||
@ -108,25 +106,37 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({ onPromptSelect, isExpande
|
|||||||
setThinkingStage("thinking");
|
setThinkingStage("thinking");
|
||||||
setIsThinking(true);
|
setIsThinking(true);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(async () => {
|
||||||
setThinkingStage("memory");
|
setThinkingStage("memory");
|
||||||
|
|
||||||
|
let responseText = promptResponses[promptToUse];
|
||||||
|
|
||||||
|
// 🔁 Fallback to Gemini if no predefined response
|
||||||
|
if (!responseText) {
|
||||||
|
try {
|
||||||
|
responseText = await generateResponse(promptToUse);
|
||||||
|
} catch (err) {
|
||||||
|
responseText = "Sorry, something went wrong while generating a response.";
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsThinking(false);
|
setIsThinking(false);
|
||||||
setThinkingStage(null);
|
setThinkingStage(null);
|
||||||
setMessages(prev => [
|
setMessages(prev => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
text: promptResponses[promptToUse] || `Let me show you detailed information about "${promptToUse}"`,
|
text: responseText,
|
||||||
isUser: false,
|
isUser: false,
|
||||||
isTyping: true,
|
isTyping: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
setTimeout(() => {
|
|
||||||
const content = getPromptContent(promptToUse);
|
const content = getPromptContent(promptToUse);
|
||||||
onPromptSelect(promptToUse, content);
|
onPromptSelect(promptToUse, content);
|
||||||
}, 9000);
|
}, 1000); // "Activating memory..." delay
|
||||||
}, 1000);
|
}, 1000); // "Thinking..." delay
|
||||||
}, 1000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -294,7 +304,7 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({ onPromptSelect, isExpande
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
// ...existing code...
|
// ...in development...
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -13,8 +13,8 @@ const DynamicContent: React.FC<DynamicContentProps> = ({ content }) => {
|
|||||||
const fetchGemini = async () => {
|
const fetchGemini = async () => {
|
||||||
if (content?.type === 'gemini' && content.prompt) {
|
if (content?.type === 'gemini' && content.prompt) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const res = await generateResponse(content.prompt, []);
|
const res = await generateResponse(content.prompt);
|
||||||
setGeminiAnswer(res.message);
|
setGeminiAnswer(res);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -48,3 +48,107 @@ const DynamicContent: React.FC<DynamicContentProps> = ({ content }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default DynamicContent;
|
export default DynamicContent;
|
||||||
|
|
||||||
|
|
||||||
|
// This would generate proper html jsx codes but it requires more advanced models
|
||||||
|
|
||||||
|
// import React, { useEffect, useState } from 'react';
|
||||||
|
// import { generateResponse } from '@/services/geminiService';
|
||||||
|
|
||||||
|
// interface DynamicContentProps {
|
||||||
|
// content: any;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const DynamicContent: React.FC<DynamicContentProps> = ({ content }) => {
|
||||||
|
// const [geminiAnswer, setGeminiAnswer] = useState<string | null>(null);
|
||||||
|
// const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const fetchGemini = async () => {
|
||||||
|
// if (content?.type === 'gemini' && content.prompt) {
|
||||||
|
// setLoading(true);
|
||||||
|
// try {
|
||||||
|
// const formattedPrompt = `
|
||||||
|
// You are an AI that outputs JSX for Tailwind-styled UI components.
|
||||||
|
|
||||||
|
// Task:
|
||||||
|
// - Return a single JSX <div> component with className="space-y-8"
|
||||||
|
// - Include a title section with heading and paragraph
|
||||||
|
// - Include 3 hardcoded MCP cards inside a grid layout
|
||||||
|
// - Each card must include: name, description, 3 features in <li>, and author
|
||||||
|
// - Use Tailwind CSS classes as shown in the example
|
||||||
|
|
||||||
|
// ⚠️ Output ONLY JSX — no explanations, no markdown, no \`\`\`jsx
|
||||||
|
|
||||||
|
// Example format:
|
||||||
|
|
||||||
|
// <div className="space-y-8">
|
||||||
|
// <div className="space-y-4">
|
||||||
|
// <h3 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||||
|
// Sample MCP Servers
|
||||||
|
// </h3>
|
||||||
|
// <p className="text-gray-600 dark:text-gray-300 leading-relaxed">
|
||||||
|
// Explore a few example MCPs you can build, deploy, and monetize on the Fastcode platform.
|
||||||
|
// </p>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <div className="grid gap-6 md:grid-cols-2">
|
||||||
|
// <div className="flex flex-col gap-3 p-6 rounded-2xl border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-sm bg-white/5 dark:bg-black/5 hover:scale-105 transition-all duration-300">
|
||||||
|
// <div className="flex items-center gap-3">
|
||||||
|
// <h4 className="font-medium text-gray-900 dark:text-white">Image Enhancer</h4>
|
||||||
|
// </div>
|
||||||
|
// <div className="text-sm text-gray-600 dark:text-gray-300">Enhance image quality with AI.</div>
|
||||||
|
// <ul className="list-disc list-inside text-xs text-gray-500 dark:text-gray-400 pl-2">
|
||||||
|
// <li>Upscale resolution</li>
|
||||||
|
// <li>Reduce noise</li>
|
||||||
|
// <li>Sharpen details</li>
|
||||||
|
// </ul>
|
||||||
|
// <div className="text-xs text-gray-400 dark:text-gray-500 mt-2">By fastcoder.ai</div>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <!-- More cards -->
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// `;
|
||||||
|
|
||||||
|
|
||||||
|
// const res = await generateResponse(formattedPrompt.trim());
|
||||||
|
// setGeminiAnswer(res);
|
||||||
|
// } catch (error) {
|
||||||
|
// setGeminiAnswer("Something went wrong while generating the response.");
|
||||||
|
// } finally {
|
||||||
|
// setLoading(false);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// fetchGemini();
|
||||||
|
// }, [content]);
|
||||||
|
|
||||||
|
// if (!content) return null;
|
||||||
|
|
||||||
|
// if (content.type === 'gemini') {
|
||||||
|
// return (
|
||||||
|
// <div className="p-6">
|
||||||
|
// <h3 className="text-lg font-semibold mb-4">Gemini Answer</h3>
|
||||||
|
// {loading ? (
|
||||||
|
// <div className="text-gray-500">Loading...</div>
|
||||||
|
// ) : (
|
||||||
|
// <div
|
||||||
|
// className="text-gray-900 dark:text-white"
|
||||||
|
// dangerouslySetInnerHTML={{ __html: geminiAnswer || '' }}
|
||||||
|
// />
|
||||||
|
// )}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (React.isValidElement(content)) return content;
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div className="p-6 text-gray-900 dark:text-white">
|
||||||
|
// {typeof content === 'string' ? content : JSON.stringify(content)}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default DynamicContent;
|
||||||
|
@ -1,71 +1,106 @@
|
|||||||
import { GoogleGenerativeAI } from '@google/generative-ai';
|
import { GoogleGenerativeAI } from '@google/generative-ai';
|
||||||
|
|
||||||
|
const GEMINI_API_KEY= 'AIzaSyAK8AyA8JYTprpqIif4qBiPql84Uh0VFh4';
|
||||||
|
|
||||||
// Initialize the Gemini API with your API key
|
// Initialize the Gemini API with your API key
|
||||||
const genAI = new GoogleGenerativeAI(process.env.NEXT_PUBLIC_GEMINI_API_KEY || '');
|
const genAI = new GoogleGenerativeAI(GEMINI_API_KEY || '');
|
||||||
|
|
||||||
const SYSTEM_PROMPT = `You are an AI assistant that helps users navigate and answer queries of a website which promotes the monetization of MCPs.`
|
const SYSTEM_PROMPT = `
|
||||||
|
You are an AI assistant for a platform that helps users discover and use MCPs (Monetizable Code Packages).
|
||||||
|
|
||||||
export const generateResponse = async (prompt: string, chatHistory: Array<{role: 'user' | 'model', parts: string}>) => {
|
- Developers can create and monetize MCPs by wrapping AI functionality into deployable, market-ready APIs.
|
||||||
try {
|
- Non-developers can use a no-code tool to build and publish their own MCPs.
|
||||||
// Get the Gemini Pro model
|
- Users interact with these MCPs through a smart chat interface, selecting the ones they want and getting tasks done directly inside the chat.
|
||||||
const model = genAI.getGenerativeModel({ model: 'gemini-pro' });
|
- Your job is to guide users in understanding and using the platform.
|
||||||
|
|
||||||
// Format chat history for the API
|
Always respond:
|
||||||
const chat = model.startChat({
|
- In friendly, simple language
|
||||||
history: [
|
- In plain text (no markdown or formatting)
|
||||||
|
- In a single paragraph under 50 words
|
||||||
|
- Without repeating or rephrasing the user's question
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
const GEMINI_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent';
|
||||||
|
|
||||||
|
export async function generateResponse(prompt: string): Promise<string> {
|
||||||
|
const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash' });
|
||||||
|
|
||||||
|
const result = await model.generateContent({
|
||||||
|
contents: [
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
parts: [{ text: SYSTEM_PROMPT }],
|
parts: [{ text: `${SYSTEM_PROMPT}\n\nUser: ${prompt}` }],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
role: 'model',
|
|
||||||
parts: [{ text: 'I understand. I will follow these guidelines when responding to questions, especially when I don\'t have complete information.' }],
|
|
||||||
},
|
|
||||||
...chatHistory.map(msg => ({
|
|
||||||
role: msg.role === 'user' ? 'user' : 'model',
|
|
||||||
parts: [{ text: msg.parts }],
|
|
||||||
})),
|
|
||||||
],
|
],
|
||||||
generationConfig: {
|
|
||||||
maxOutputTokens: 1000,
|
|
||||||
temperature: 0.7,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send the message and get the response
|
|
||||||
const result = await chat.sendMessage(prompt);
|
|
||||||
const response = await result.response;
|
const response = await result.response;
|
||||||
const text = response.text();
|
const text = response.text();
|
||||||
|
return text || "I'm not sure about that.";
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
// export const generateResponse = async (prompt: string, chatHistory: Array<{role: 'user' | 'model', parts: string}>) => {
|
||||||
success: true,
|
// try {
|
||||||
message: text,
|
// // Get the Gemini Pro model
|
||||||
};
|
// const model = genAI.getGenerativeModel({ model: 'gemini-pro' });
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating response:', error);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: 'Sorry, I encountered an error while processing your request. Please try again later.'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const isQuestionUnknown = (response: string): boolean => {
|
// // Format chat history for the API
|
||||||
// Simple check for phrases that might indicate the model doesn't know the answer
|
// const chat = model.startChat({
|
||||||
const unknownPhrases = [
|
// history: [
|
||||||
'i don\'t know',
|
// {
|
||||||
'i\'m not sure',
|
// role: 'user',
|
||||||
'i don\'t have that information',
|
// parts: [{ text: SYSTEM_PROMPT }],
|
||||||
'i don\'t have specific information',
|
// },
|
||||||
'i don\'t have access to',
|
// {
|
||||||
'i don\'t have the capability',
|
// role: 'model',
|
||||||
'i don\'t have enough information',
|
// parts: [{ text: 'I understand. I will follow these guidelines when responding to questions, especially when I don\'t have complete information.' }],
|
||||||
'i can\'t provide',
|
// },
|
||||||
'i\'m unable to',
|
// ...chatHistory.map(msg => ({
|
||||||
'i don\'t have the ability',
|
// role: msg.role === 'user' ? 'user' : 'model',
|
||||||
];
|
// parts: [{ text: msg.parts }],
|
||||||
|
// })),
|
||||||
|
// ],
|
||||||
|
// generationConfig: {
|
||||||
|
// maxOutputTokens: 1000,
|
||||||
|
// temperature: 0.7,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
return unknownPhrases.some(phrase =>
|
// // Send the message and get the response
|
||||||
response.toLowerCase().includes(phrase)
|
// const result = await chat.sendMessage(prompt);
|
||||||
);
|
// const response = await result.response;
|
||||||
};
|
// const text = response.text();
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// success: true,
|
||||||
|
// message: text,
|
||||||
|
// };
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error('Error generating response:', error);
|
||||||
|
// return {
|
||||||
|
// success: false,
|
||||||
|
// message: 'Sorry, I encountered an error while processing your request. Please try again later.'
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export const isQuestionUnknown = (response: string): boolean => {
|
||||||
|
// // Simple check for phrases that might indicate the model doesn't know the answer
|
||||||
|
// const unknownPhrases = [
|
||||||
|
// 'i don\'t know',
|
||||||
|
// 'i\'m not sure',
|
||||||
|
// 'i don\'t have that information',
|
||||||
|
// 'i don\'t have specific information',
|
||||||
|
// 'i don\'t have access to',
|
||||||
|
// 'i don\'t have the capability',
|
||||||
|
// 'i don\'t have enough information',
|
||||||
|
// 'i can\'t provide',
|
||||||
|
// 'i\'m unable to',
|
||||||
|
// 'i don\'t have the ability',
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// return unknownPhrases.some(phrase =>
|
||||||
|
// response.toLowerCase().includes(phrase)
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
@ -6,6 +6,7 @@ import HowToEarnContent from '../components/content/HowToEarnContent';
|
|||||||
import WhatCanHelpContent from '../components/content/WhatCanHelpContent';
|
import WhatCanHelpContent from '../components/content/WhatCanHelpContent';
|
||||||
import Developers from '@/components/content/Developers';
|
import Developers from '@/components/content/Developers';
|
||||||
import SampleMCPs from '@/components/content/SampleMCPs';
|
import SampleMCPs from '@/components/content/SampleMCPs';
|
||||||
|
import DynamicContent from '@/components/content/DynamicContent';
|
||||||
|
|
||||||
export const getPromptContent = (prompt: string) => {
|
export const getPromptContent = (prompt: string) => {
|
||||||
switch (prompt) {
|
switch (prompt) {
|
||||||
@ -39,10 +40,15 @@ export const getPromptContent = (prompt: string) => {
|
|||||||
title: "Sample MCP Servers",
|
title: "Sample MCP Servers",
|
||||||
component: <SampleMCPs />
|
component: <SampleMCPs />
|
||||||
};
|
};
|
||||||
|
// case "Ask Gemini":
|
||||||
|
// return {
|
||||||
|
// title: "Gemini Answer",
|
||||||
|
// component: <DynamicContent content={{ type: 'gemini', prompt }} />
|
||||||
|
// }
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
title: "Information",
|
title: "Gemini Answer",
|
||||||
component: <div className="text-gray-600 dark:text-gray-300">Content for "{prompt}" coming soon...</div>
|
component: <DynamicContent content={{ type: 'gemini', prompt }} />
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user