From 5d189ceb2873187ac36a07d44e012e98077feb98 Mon Sep 17 00:00:00 2001 From: ehsanghaffarii Date: Mon, 27 May 2024 13:42:55 +0330 Subject: [PATCH] Update bio template and enhance API functionality --- app/api/langchain/route.ts | 27 +++++++++++---- app/page.tsx | 69 ++++++++++++++++++-------------------- libs/Langchain.ts | 4 +-- libs/utils.ts | 17 ++++++++-- types/types.ts | 8 +++++ 5 files changed, 78 insertions(+), 47 deletions(-) diff --git a/app/api/langchain/route.ts b/app/api/langchain/route.ts index c561269..3b80753 100644 --- a/app/api/langchain/route.ts +++ b/app/api/langchain/route.ts @@ -5,15 +5,24 @@ import { z } from "zod"; import { createStructuredOutputChainFromZod } from "langchain/chains/openai_functions"; import { PromptTemplate } from "@langchain/core/prompts"; import { createOpenAIModel } from "@/libs/Langchain"; -import { getIP } from "@/libs/utils"; +import { createUserMessage, getIP } from "@/libs/utils"; import { checkRateLimit } from "@/store/rateLimitStore"; export const runtime = "edge"; -const TEMPLATE = `Generate a compelling social media bio for user centered around context which them provide you. -The bio should be concise (150-200 characters) and capture the essence of user in a way that resonates with context. -Include elements that showcase personality, passion, and any relevant hashtags or keywords. -Feel free to add a touch of creativity to make it engaging. +const TEMPLATE = `Craft a personalized social media bio in Farsi (Persian) that captures the essence of the user, based on the specific vibe they choose: advanced, normal, or joke. This bio should weave together their personality, passions, and context into a narrative that aligns with their selected vibe. + +Guidelines: + +Language: The bio must be written in Farsi (Persian) to connect authentically with the target linguistic audience. +Vibe Options: + - advanced: Create a bio with a sophisticated, professional tone, showcasing achievements and expertise. + - normal: Ensure the bio is relatable and down-to-earth, highlighting everyday interests and personal traits. + - joke: Infuse the bio with humor, making it light-hearted and entertaining while still capturing the user's essence. +Length: Maintain a concise length of 150-200 characters to ensure the bio is both impactful and suitable for social media. +Content: Emphasize personality traits, passions, and include relevant keywords that resonate with their vibe choice and interests. +Creativity: Add a unique creative flair to make the bio captivating and reflective of the chosen vibe, ensuring it stands out. + {input}`; @@ -29,7 +38,11 @@ export async function POST(req: NextRequest) { return NextResponse.json({ error: "شما بیش از حد مجاز از سرویس استفاده کرده اید. چند ساعت بعد امتحان کنید" }, { status: 429 }); } - const messages = await req.json() + console.log(`USER IP: ${ip}`) + + const userMessage = await req.json() + + const messages = createUserMessage(userMessage) const prompt = PromptTemplate.fromTemplate<{ input: string }>(TEMPLATE); @@ -45,13 +58,13 @@ export async function POST(req: NextRequest) { }); + console.log(prompt) const chain = createStructuredOutputChainFromZod(schema, { llm: model, prompt, outputKey: "output", }); - console.log(chain) const result = await chain.call({ input: messages, diff --git a/app/page.tsx b/app/page.tsx index 9177551..2a183b8 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -9,18 +9,18 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { Toaster, toast } from "react-hot-toast"; import { CheckSquare, Loader2 } from "lucide-react"; import { Textarea } from "@/components/ui/textarea"; import { toast as sonnar } from "sonner"; import { Button } from "@/components/ui/button"; -import { GeneratedBio } from "@/types/types"; +import { GeneratedBio, UserInputPayload, VibeType } from "@/types/types"; + -export type VibeType = "حرفه‌ای" | "معمولی" | "طنز"; let vibes: VibeType[] = ["حرفه‌ای", "معمولی", "طنز"]; -const NEXT_PUBLIC_COOLDOWN_TIME = process.env.NEXT_PUBLIC_COOLDOWN_TIME +const NEXT_PUBLIC_COOLDOWN_TIME = process.env.NEXT_PUBLIC_COOLDOWN_TIME || 10 const BioGenerator = () => { const [loading, setLoading] = useState(false); @@ -51,9 +51,12 @@ const BioGenerator = () => { } }; - const handleBioChange = (event: React.ChangeEvent) => { - setBio(event.target.value); - }; + const handleBioChange = useCallback( + (event: React.ChangeEvent) => { + setBio(event.target.value); + }, + [] + ); const generateBio = async ( e: React.MouseEvent @@ -74,21 +77,18 @@ const BioGenerator = () => { setCooldownTimer(NEXT_PUBLIC_COOLDOWN_TIME); try { - const messages = `Generate 2 ${vibe} biographies with no hashtags, in Persian language. ${ - vibe === "طنز" - ? "Make sure there is a joke in there and it's a little ridiculous." - : "" - } base them on this context: ${bio}${bio.slice(-1) === "." ? "" : " "}`; + const userInput: UserInputPayload = { + vibe, + bio, + }; const response = await fetch("/api/langchain", { method: "POST", - mode: "no-cors", headers: { "Content-Type": "application/json", }, - body: JSON.stringify(messages), + body: JSON.stringify(userInput), }); - console.log(response); if (!response.ok) { const errormessage = await response.json(); @@ -97,15 +97,13 @@ const BioGenerator = () => { duration: 15000, className: "text-base", }); + return; } - if (response.ok) { - const data = await response.json(); - - const allBios: GeneratedBio[] = data.output; - setGeneratedBios(allBios); - scrollToBios(); - } + const data = await response.json(); + const allBios: GeneratedBio[] = data.output; + setGeneratedBios(allBios); + scrollToBios(); } catch (error) { const err = error as Error; console.log(err); @@ -122,18 +120,17 @@ const BioGenerator = () => { <>
-

- با

+

+ با +

ClubGPT icon -

- برای خودت بایو حـرفه‌ای بساز 😎 -

+ alt="ClubGPT icon" + src="/screenshot.png" + className="sm:w-36" + width={100} + height={50} + /> +

برای خودت بایو حـرفه‌ای بساز 😎

@@ -195,7 +192,7 @@ const BioGenerator = () => { className={`w-full rounded-md text-white font-semibold px-4 py-3 sm:mt-10 mt-8 ${ bio.length === 0 || isCooldown ? "bg-orange-600" : "bg-black" } ${isCooldown ? "hover:bg-orange-600" : "hover:bg-black/70"}`} - onClick={(e) => generateBio(e)} + onClick={generateBio} disabled={bio.length === 0} > {isCooldown @@ -208,7 +205,7 @@ const BioGenerator = () => { className="w-full bg-black rounded-lg text-white font-medium gap-2 px-4 py-2 sm:mt-10 mt-8 hover:bg-black/80" disabled > - در حال فکر کردن + در حال فکر کردن )}
@@ -218,7 +215,7 @@ const BioGenerator = () => { toastOptions={{ duration: 2000 }} />
-
+
{generatedBios && generatedBios.map((bio) => ( diff --git a/libs/Langchain.ts b/libs/Langchain.ts index 187339b..d45871a 100644 --- a/libs/Langchain.ts +++ b/libs/Langchain.ts @@ -3,8 +3,8 @@ import { ChatOpenAI } from "@langchain/openai"; export const createOpenAIModel = (apiKey: string) => { const model = new ChatOpenAI({ apiKey: apiKey, - temperature: 0.8, - modelName: "gpt-4", + temperature: 0.1, + modelName: "gpt-4o", }); return model; } \ No newline at end of file diff --git a/libs/utils.ts b/libs/utils.ts index c55b6f7..a629dad 100644 --- a/libs/utils.ts +++ b/libs/utils.ts @@ -1,4 +1,4 @@ -import ServerError from "@/types/types"; +import ServerError, { UserInputPayload } from "@/types/types"; import { type ClassValue, clsx } from "clsx" import { NextRequest, NextResponse } from "next/server"; import { twMerge } from "tailwind-merge" @@ -35,7 +35,20 @@ export function getIP(req: NextRequest) { if (!ip && forwardedFor) { ip = forwardedFor.split(",").at(0) ?? ""; } - return ip; } + +export const createUserMessage = (input: UserInputPayload) => { + let userVibe = "" + if (input.vibe === "حرفه‌ای") { + userVibe = "Advanced" + } else if (input.vibe === "طنز") { + userVibe = "Joke" + } else if (input.vibe === "معمولی") { + userVibe = "Normal" + } + const messages = `Generate 2 ${userVibe} bios.base them on this context: ${input.bio}${input.bio.slice(-1) === "." ? "" : " "}`; + + return messages +} diff --git a/types/types.ts b/types/types.ts index 5b18c0b..6d0f25c 100644 --- a/types/types.ts +++ b/types/types.ts @@ -15,4 +15,12 @@ export type JWTPayload = { export interface GeneratedBio { id: string; content: string; +} + +export type VibeType = "حرفه‌ای" | "معمولی" | "طنز"; + + +export interface UserInputPayload { + vibe: VibeType; + bio: string; } \ No newline at end of file