cover-img

Cara Membuat AI Assistant untuk Portfolio Kamu

Tips Membuat AI yang Siap Menjawab Semua Pertanyaan Rekruter Berdasarkan Data Kamu

6 February, 2025

0

0

0

Manfaatkan teknologi AI seperti Gemini atau Deepseek AI untuk menjawab semua pertanyaan rekruter tentang diri Kamu. Dengan AI, Kamu bisa membuat proses rekrutmen lebih efisien dan profesional.

Peran AI dalam Mengubah Cara Kerja Manusia

Pada era digital ini, Artificial Intelligence (AI) sudah menjadi bagian tak terpisahkan dari kehidupan sehari-hari. Kehadiran AI telah membantu manusia dalam menyelesaikan berbagai tugas, termasuk di bidang pemrograman.

Bayangkan, sebagai programmer, Kamu mungkin menghabiskan waktu berjam-jam untuk menyelesaikan sebuah bug yang sulit. Namun, dengan bantuan AI, masalah tersebut bisa diselesaikan dalam waktu kurang dari 2 jam.

Apakah Kamu pernah mengalami hal serupa? Yuk, bagikan pengalaman Kamu di kolom komentar!

Membuat AI Assistant untuk Portfolio

Tujuan artikel ini adalah membantu Kamu mengimplementasikan AI secara sederhana untuk membuat AI Assistant yang bisa menjawab pertanyaan tentang diri Kamu, seperti pengalaman kerja, kemampuan teknis, status freelance, dan lainnya.

Kamu mungkin sudah familiar dengan ChatGPT, Gemini AI, atau Deepseek AI. Nah, kita akan mencoba mengimplementasikan salah satu AI tersebut ke dalam portfolio Kamu.

Langkah 1: Siapkan Project Portfolio

Artikel ini tidak membahas cara membuat portfolio dari awal. Pastikan Kamu sudah memiliki website portfolio sendiri. Saya sendiri menggunakan Next.js untuk portfolio saya.

Di sini, saya sudah memiliki beberapa komponen:

  1. Fixed Button Chat (Tombol Chat Tetap di Sudut Kanan Bawah)

2. Chat Window (Jendela Chat)

Secara alur, ketika tombol chat diklik, jendela chat akan muncul.


Langkah 2: Menggunakan Gemini AI

Untuk menggunakan Gemini AI, ikuti langkah-langkah berikut:

  1. Kunjungi AI Studio Google dan daftar.
  2. Setelah login, cari tab Get API Key.
  3. Klik Create API Key untuk mendapatkan kunci API.

Langkah 3: Membuat file get knowledge di Next.js

Di Next.js, saya membuat struktur API chat seperti ini:

  1. knowledge.ts (berfungsi untuk mengambil knowledge tentang diri saya.
  2. request pertama ambil ke DB kemudian selanjutnya akan mengambil redis, saya menggunakan upstash redis (tersedia di vercel)
// App/Api/knowledge.ts
import { Redis } from '@upstash/redis'
const redis = new Redis({
url: process.env.KV_REST_API_URL || '', // Use REST API URL instead of Redis URL
token: process.env.KV_REST_API_TOKEN || ''
})

const CACHE_TTL = 3600 // Cache for 1 hour
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL;

// Add error handling wrapper
const getCache = async (key: string) => {
try {
const cached = await redis.get(key)
// Check if cached is already an object
return cached && typeof cached === 'object' ? cached :
cached ? JSON.parse(cached as string) : null
} catch (error) {
console.error(`Redis cache error for ${key}:`, error)
return null
}
}

// Add logging wrapper function
const logDataSource = (key: string, fromCache: boolean) => {
console.log(`[${key.toUpperCase()}] Getting data from: ${fromCache ? 'Redis Cache' : 'API'}`);
}
// Use this function instead of static data
export async function getProjects() {
const cachedProjects = await getCache('projects')
if (cachedProjects) {
logDataSource('projects', true);
return cachedProjects
}

logDataSource('projects', false);
const response = await fetch(`${BASE_URL}/api/projects`, {
headers: {
'Content-Type': 'application/json',
}
})

const data = await response.json()

// Ensure we're storing a string in Redis
await redis.set('projects', typeof data.projects === 'string' ?
data.projects :
JSON.stringify(data.projects), {
ex: CACHE_TTL
})

return data.projects
}

export async function getBootcamps() {
const cachedBootcamps = await getCache('bootcamps')
if (cachedBootcamps) {
logDataSource('bootcamps', true);
return cachedBootcamps
}

logDataSource('bootcamps', false);
const response = await fetch(`${BASE_URL}/api/bootcamps`, {
headers: {
'Content-Type': 'application/json',
}
})
const data = await response.json()

await redis.set('bootcamps', JSON.stringify(data.bootcamps), {
ex: CACHE_TTL
})

return data.bootcamps
}

export async function getProfile() {
const cachedProfile = await getCache('profile')
if (cachedProfile) {
logDataSource('profile', true);
return cachedProfile
}

logDataSource('profile', false);
const response = await fetch(`${BASE_URL}/api/profile/677b31c9a3f8c7b6de5f52d0`, {
headers: {
'Content-Type': 'application/json',
}
})
const data = await response.json()

await redis.set('profile', JSON.stringify(data.profile), {
ex: CACHE_TTL
})

return data.profile
}

export async function getExperiences() {
const cachedExperiences = await getCache('experiences')
if (cachedExperiences) {
logDataSource('experiences', true);
return cachedExperiences
}

logDataSource('experiences', false);
const response = await fetch(`${BASE_URL}/api/experiences/677b31c9a3f8c7b6de5f52d0`, {
headers: {
'Content-Type': 'application/json',
}
})
const data = await response.json()

await redis.set('experiences', JSON.stringify(data.experiences), {
ex: CACHE_TTL
})

return data.experiences
}

Langkah 4: Mengintegrasikan Gemini AI ke dalam Portfolio

Setelah menyiapkan knowledge file, langkah selanjutnya adalah mengintegrasikan Gemini AI ke dalam portfolio Kamu. Berikut adalah contoh kode untuk melakukan request ke API Gemini:

  1. Mengambil message dari request (pertanyaan yang diajukan pengguna) 
  2. Mengambil data knowledge (informasi tentang diri kita) 
  3. Membuat context (tahap ini meng group kan context berdasarkan category tertentu, lihat di full source code dibawah) 
  4. Setelah memiliki context, gunakan context tersebut di prompt ketika akan request ke gemini api
// App/Api/route.ts
import { NextResponse } from 'next/server'
import { getProjects, getBootcamps, getProfile, getExperiences } from './knowledge'

const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const GEMINI_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent';
async function generateGeminiResponse(message: string, context: string) {
try {
const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [{
parts: [{
text: `You are an AI assistant that only answers questions about Fajar Mukti Hidayat's portfolio.
Use this context for responses: ${context}

User question: ${message}`
}]
}]
})
});
const data = await response.json();
return data.candidates?.[0]?.content?.parts?.[0]?.text || 'Sorry, I could not generate a response.';
} catch (error) {
console.error('Error calling Gemini API:', error);
throw new Error('Failed to generate response');
}
}

saya berkata pada gemini, untuk jadi Ai Asistant yang akan menjawab semua pertanyaan tentang portfolio fajar mukti hidayat dan memberikan greeting jika user hanya menyapa. selain itu (diluar context) tidak perlu dijawab. dibawah ini adalah full code dari proses reques

import { NextResponse } from 'next/server'
import { getProjects, getBootcamps, getProfile, getExperiences } from './knowledge'

interface Bootcamp {
_id: string
title: string
description: string
projects: string[]
certificateLink: string
courseLink: string
detailedDescription: string,
techStack: { name: string; icon: string }[],
toDetail: string
}

interface Project {
_id: string
title: string
description: string
longDescription: string
tags: string[]
github: string
demo: string
}

interface SocialMedia {
_id: string
platform: string
url: string
}

interface Experience {
id: string
company: string
position: string
startDate: string
endDate: string
description: string
responsibilities?: string[]
}

const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const GEMINI_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent';

async function generateGeminiResponse(message: string, context: string) {
try {
const response = await fetch(`${GEMINI_URL}?key=${GEMINI_API_KEY}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [{
parts: [{
text: `You are an AI assistant that only answers questions about Fajar Mukti Hidayat's portfolio. and
give greetings to the user.
Use this context for responses: ${context}

User question: ${message}`
}]
}]
})
});

const data = await response.json();
return data.candidates?.[0]?.content?.parts?.[0]?.text || 'Sorry, I could not generate a response.';
} catch (error) {
console.error('Error calling Gemini API:', error);
throw new Error('Failed to generate response');
}
}

export async function POST(request: Request) {
try {
console.log('1. Starting chat request...');
const { message } = await request.json()

console.log('2. Fetching data...');
const [projects, bootcamps, profile, experiences] = await Promise.all([
getProjects(),
getBootcamps(),
getProfile(),
getExperiences()
])

console.log('3. Creating context...');
const context = `
<PROFILE>
Name: Fajar Mukti Hidayat
${profile?.greeting || ''}
</PROFILE>

<SOCIAL>
${profile?.socialMediaLinks?.map((social: SocialMedia) =>
`${social.platform}: ${social.url}`
).join('\n')}
</SOCIAL>

<CAREER_AND_EXPERIENCE>
Work History:
${experiences?.map((exp: Experience) => `
Company: ${exp.company}
Role: ${exp.position}
Duration: ${exp.startDate} - ${exp.endDate}
Responsibilities: ${exp.description}
${exp.responsibilities ? `Key Tasks:\n${exp.responsibilities.map(r => `- ${r}`).join('\n')}` : ''}
`).join('\n---\n')}
</CAREER_AND_EXPERIENCE>

<PROJECTS>
${projects?.map((p: Project) => `
Title: ${p.title}
toDetail: ${process.env.NEXT_PUBLIC_SITE_URL}/projects/${p._id}
Description: ${p.description}
Tech: ${p.tags.join(', ')}
${p.github !== '#' ? `GitHub: ${p.github}` : ''}
${p.demo !== '#' ? `Demo: ${p.demo}` : ''}`
).join('\n---\n')}
</PROJECTS>

<EDUCATION>
${bootcamps?.map((b: Bootcamp) => `
Title: ${b.title}
Description: ${b.description}
toDetail: ${process.env.NEXT_PUBLIC_SITE_URL}/bootcamp/${b._id}
Skills: ${b.techStack.map(t => t.name).join(', ')}`
).join('\n---\n')}
</EDUCATION>

<FREELANCE>
latest project freelance at berkatsoft , making a mobile app with flutter and laravel.
availability for freelancing is not available.
<FREELANCE>
`

console.log('4. Sending to GEMINI API...', process.env.GEMINI_API_KEY);
console.log('Context:', context);

// Log Groq API request
console.log('7. Making GEMINI API request...');
const response = await generateGeminiResponse(message, context);

return NextResponse.json({ response })

} catch (error) {
console.error('ERROR in chat processing:', error);
return NextResponse.json(
{ error: 'Failed to process request' },
{ status: 500 }
)
}
}

Hasil Integrasi AI ke dalam Portfolio

Dengan mengikuti langkah-langkah di atas, Kamu sudah berhasil mengintegrasikan AI Assistant ke dalam portfolio. Sekarang, portfolio Kamu bisa menjawab pertanyaan rekruter secara otomatis, memberikan informasi tentang pengalaman kerja, proyek, dan kemampuan teknis Kamu.

Kunjungi Portfolio saya untuk melihat implementasinya secara langsung

https://fajarmukti.com


0

0

0

Fajar Mukti Hidayat
Full Stack Engineer

More Articles

Showwcase is a professional tech network with over 0 users from over 150 countries. We assist tech professionals in showcasing their unique skills through dedicated profiles and connect them with top global companies for career opportunities.

© Copyright 2025. Showcase Creators Inc. All rights reserved.