Skip to content

Commit

Permalink
fix: correct hardcoded url and change added routes in right file (#4)
Browse files Browse the repository at this point in the history
* fix: correct dotenv import and enhance error handling for OpenAI API key
feat: implement chat functionality in api_service and update API routes

* fix: remove console log and dotnet

* fix: problem with pr

* fixup!
  • Loading branch information
ernestocarocca authored Dec 5, 2024
1 parent 99345d6 commit 9c5a64d
Show file tree
Hide file tree
Showing 7 changed files with 1,753 additions and 738 deletions.
2,365 changes: 1,689 additions & 676 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"dependencies": {
"@fastify/cors": "^8.2.0",
"@fastify/env": "^5.0.1",
"@fastify/static": "^7.0.4",
"@fastify/swagger": "^8.3.1",
"@fastify/swagger-ui": "^1.5.0",
Expand All @@ -31,6 +32,7 @@
"@tabler/icons-react": "^3.19.0",
"dotenv": "^16.4.6",
"fastify": "4.23.2",
"fastify-env": "^2.1.1",
"next": "^14.2.15",
"nodemon": "^2.0.20",
"openai": "^4.74.0",
Expand Down
46 changes: 2 additions & 44 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import { Static, Type } from '@sinclair/typebox';
import { FastifyPluginCallback } from 'fastify';
import apiService from './api_service';

import { OpenAI } from 'openai';
import dotenv from 'dotenv';
dotenv.config();

const openAiApiKey = process.env.OPENAI_API_KEY as string;
const HelloWorld = Type.String({
description: 'The magical words!'
});
Expand Down Expand Up @@ -40,42 +37,7 @@ const healthcheck: FastifyPluginCallback<HealthcheckOptions> = (
);
next();
};
const aiMassage: FastifyPluginCallback = (fastify, opts, next) => {
async function chat(reply: any, userMessage: string) {
const openai = process.env.OPENAI_API_KEY as string;
if (!openai) {
throw new Error(
'The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: "My API Key" }).'
);
}
const client = new OpenAI({ apiKey: openai });
reply.raw.setHeader('Content-Type', 'text/event-stream');
reply.raw.setHeader('Cache-Control', 'no-cache');
reply.raw.setHeader('Connection', 'keep-alive');

const chatCompletion = await client.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{
role: 'assistant',
content: [{ type: 'text', text: "Who's there?" }]
},
{ role: 'user', content: userMessage }
]
});

return reply.send(chatCompletion.choices[0].message.content);
}
fastify.get('/chat', async (_, reply) => {
await chat(reply, 'Hello');
});
fastify.post('/chat/message', async (request, reply) => {
const userMessage = request.body as string;
await chat(reply, userMessage);
});
next();
};
export interface ApiOptions {
title: string;
}
Expand Down Expand Up @@ -104,14 +66,10 @@ export default (opts: ApiOptions) => {

api.register(healthcheck, { prefix: '/api', title: opts.title });
// register other API routes here
api.register(aiMassage);

if (!process.env.OPENAI_API_KEY) {
throw new Error('OPENAI_API_KEY is required');
}
api.register(apiService, {
prefix: '/api/v1',
openAiApiKey: process.env.OPENAI_API_KEY
openAiApiKey: openAiApiKey as string
});

return api;
Expand Down
29 changes: 27 additions & 2 deletions src/api_service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FastifyPluginCallback } from 'fastify';
import { FastifyPluginCallback, FastifyReply } from 'fastify';
import OpenAI from 'openai';

export interface ApiServiceOptions {
openAiApiKey: string;
Expand All @@ -9,11 +10,35 @@ const apiService: FastifyPluginCallback<ApiServiceOptions> = (
opts,
next
) => {
fastify.post('/message', async (request, reply) => {
const userMessage = request.body as string;
await chat(reply, userMessage);
});
fastify.setErrorHandler((error, request, reply) => {
reply.code(500).send({ reason: error.message });
});

// Insert routes here
async function chat(reply: FastifyReply, userMessage: string) {
const openai = opts.openAiApiKey;
if (!openai) {
throw new Error('OpenAI API key is required');
}

const client = new OpenAI({ apiKey: openai });
reply.raw.setHeader('Content-Type', 'text/event-stream');
reply.raw.setHeader('Cache-Control', 'no-cache');
reply.raw.setHeader('Connection', 'keep-alive');

const chatCompletion = await client.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: userMessage }
]
});

return reply.send(chatCompletion.choices[0].message.content);
}

next();
};
Expand Down
17 changes: 16 additions & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@tailwind utilities;

:root {
--background: #0a0a0a;
--background: transparent;
--foreground: #ededed;
}

Expand All @@ -18,3 +18,18 @@ body {
text-wrap: balance;
}
}
.glassmorphism {
background: linear-gradient(from left, right, to right-d, #51259dff, #00bcd4);
backdrop-filter: blur(7px);
border: 2px solid rgba(205, 118, 205, 0.2);
border-radius: 10px;
}
.gradient-text {
background: linear-gradient(to right, rgb(140, 96, 214), #00bcd4);
-webkit-text-fill-color: transparent;
background-clip: text;
-webkit-background-clip: text;
}
.gradient-bg {
background: linear-gradient(to bottom, right, to right, #7e57c2, #00bcd4);
}
4 changes: 2 additions & 2 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={`antialiased dark text-foreground bg-background`}>
<html lang="en" className="w-screen h-screen bg-transparent">
<body className={`antialiased dark text-foreground `}>
<Providers>{children}</Providers>
</body>
</html>
Expand Down
28 changes: 15 additions & 13 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { Card, CardHeader, CardBody } from '@nextui-org/card';
import { Button, Spacer } from '@nextui-org/react';
import { IconArrowUp, IconTrash } from '@tabler/icons-react';
import { Textarea } from '@nextui-org/input';
import { useApiUrl } from '@/hooks/useApiUrl';

export default function Page() {
const [response, setResponse] = useState('');
const [loading, setLoading] = useState(false);
const [input, setInput] = useState('');
const [error, setError] = useState('');
const url = useApiUrl();

const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
setInput(event.target.value);
Expand All @@ -19,11 +21,10 @@ export default function Page() {
setLoading(true);

try {
const response = await fetch('http://localhost:8000/chat/message', {
const response = await fetch(`${url}/message`, {
method: 'POST',
body: JSON.stringify({ userMessage: input })
});
console.log('response', response);
if (response.ok) {
setResponse(await response.text());
}
Expand All @@ -34,27 +35,28 @@ export default function Page() {
};

return (
<div className=" w-screen h-screen glassmorphism">
<Card className="w-full h-full fixed py-2 bg-transparent ">
<div className="w-screen h-screen glassmorphism ">
<Card radius="none" className="w-full h-full bg-transparent">
<div className=" flex">
<Button className=" bg-transparent " isIconOnly>
<IconTrash color="gray" size={24} />
<Button isIconOnly className="bg-transparen">
<IconTrash color="purple" size={24} />
</Button>
<CardHeader className="text-center fonst-bold text-white">
Chat with AI
<CardHeader className="text-center gradient-text font-extrabold">
Chat-Agent by Eyevinn Technology OSC
</CardHeader>
</div>
<Spacer y={10} />
<CardBody className="flex-grow text-white font-bold">
<Spacer y={1} />
<CardBody className="flex-grow text-white font-bold p-3">
{loading && <p>Loading...</p>}
{error && <p>{error}</p>}
{response && <p>{response}</p>}
</CardBody>
<div className="flex bg-gray-200 flex-grow items-center p-2 overflow-scroll">
<div className="flex flex-grow items-center p-3 overflow-scroll">
<Textarea
value={input}
onChange={handleInputChange}
type="text"
placeholder="Type your question..."
placeholder="Ask me anything"
minRows={1}
maxRows={4}
/>
Expand All @@ -63,7 +65,7 @@ export default function Page() {
isIconOnly
className="bg-secondary py-1 mr-0 mb-2 ml-2 h-[30px] w-[32px] rounded-full"
>
<IconArrowUp size={30} stroke={3} />
<IconArrowUp color="gray" size={30} stroke={3} />
</Button>
</div>
</Card>
Expand Down

0 comments on commit 9c5a64d

Please sign in to comment.