From 9cccdfe5c63b3569c373e79d773ad8f6517d01c4 Mon Sep 17 00:00:00 2001 From: wslyvh Date: Tue, 29 Oct 2024 13:01:58 +0100 Subject: [PATCH 1/2] same site --- devcon-api/src/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devcon-api/src/app.ts b/devcon-api/src/app.ts index d81bff896..8c269b450 100644 --- a/devcon-api/src/app.ts +++ b/devcon-api/src/app.ts @@ -41,7 +41,7 @@ const sessionConfig: SessionOptions = { if (SERVER_CONFIG.NODE_ENV === 'production') { app.set('trust proxy', 1) // for secure cookies and when using HTTPS: https://expressjs.com/en/guide/behind-proxies.html - sessionConfig.cookie = { ...sessionConfig.cookie, secure: true } + sessionConfig.cookie = { ...sessionConfig.cookie, secure: true, sameSite: 'none' } } app.use(session(sessionConfig)) From 0d62f8969d4d4fb3995cb4f9a9258036c6a69308 Mon Sep 17 00:00:00 2001 From: lassejaco Date: Tue, 29 Oct 2024 15:07:19 +0100 Subject: [PATCH 2/2] new ai --- .github/workflows/ai-content-prep.yml | 2 +- devcon-api/src/controllers/ai.ts | 36 ++++++------- devcon-api/src/services/ai/open-ai/open-ai.ts | 51 ++++++++++++++++-- devcon/cms/pages/ai_context.mdx | 8 +-- devcon/src/ai/open-ai.ts | 53 +++++++++++++++++-- devcon/src/ai/sync-vector-store.ts | 1 + 6 files changed, 119 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ai-content-prep.yml b/.github/workflows/ai-content-prep.yml index 2f9fe6df7..6309ca41e 100644 --- a/.github/workflows/ai-content-prep.yml +++ b/.github/workflows/ai-content-prep.yml @@ -58,7 +58,7 @@ jobs: run: | touch .env echo OPEN_AI_KEY='${{ secrets.OPEN_AI_KEY }}' >> .env - echo OPEN_AI_ASSISTANT_ID='asst_fUtZhDjL35nZBBog2bJTKNoy' >> .env + echo OPEN_AI_ASSISTANT_ID='asst_B3UJxQ8V53rmVWxaqu3Iraif' >> .env echo GITHUB_SHA='${{ github.sha }}' >> .env - name: Run script diff --git a/devcon-api/src/controllers/ai.ts b/devcon-api/src/controllers/ai.ts index 8c5aaafc7..e46002ff7 100644 --- a/devcon-api/src/controllers/ai.ts +++ b/devcon-api/src/controllers/ai.ts @@ -48,7 +48,7 @@ aiRouter.post('/devabot', async (req: Request, res: Response) => { try { // Create a stream for the AI response - const stream = await api.createMessageStream('asst_fUtZhDjL35nZBBog2bJTKNoy', message, threadID) + const stream = await api.createMessageStream('asst_B3UJxQ8V53rmVWxaqu3Iraif', message, threadID) // Set headers for streaming res.writeHead(200, { @@ -71,21 +71,19 @@ aiRouter.post('/devabot', async (req: Request, res: Response) => { } }) -aiRouter.post('/devabot/recommendations', async (req: Request, res: Response) => { - const { message } = req.body - - try { - const recommendations = await api.recommendations.getScheduleRecommendations('asst_PRn8YEfa54OGfroaVFhvLWlv', message) - - res.json(recommendations) - } catch (e: any) { - console.error(e, 'error') - if (e.error) { - res.status(500).json({ error: e.error }) - } else { - res.status(500).json({ error: 'Internal Server Error' }) - } - } -}) - -// Every 5 minutes, update programming data - if version is different than the one uploaded to openai, update the vector store +// aiRouter.post('/devabot/recommendations', async (req: Request, res: Response) => { +// const { message } = req.body + +// try { +// const recommendations = await api.recommendations.getScheduleRecommendations('asst_PRn8YEfa54OGfroaVFhvLWlv', message) + +// res.json(recommendations) +// } catch (e: any) { +// console.error(e, 'error') +// if (e.error) { +// res.status(500).json({ error: e.error }) +// } else { +// res.status(500).json({ error: 'Internal Server Error' }) +// } +// } +// }) diff --git a/devcon-api/src/services/ai/open-ai/open-ai.ts b/devcon-api/src/services/ai/open-ai/open-ai.ts index 024892b22..8741e2e2a 100644 --- a/devcon-api/src/services/ai/open-ai/open-ai.ts +++ b/devcon-api/src/services/ai/open-ai/open-ai.ts @@ -164,7 +164,14 @@ export const api = (() => { await openai.beta.threads.messages.create(threadID, { role: 'user', - content: `${userMessage}\nSystem: The current date is: ${new Date().toLocaleDateString()}.`, + content: `${userMessage}\nSystem: The current date and time is: ${new Date().toLocaleString('en-US', { + timeZone: 'Asia/Bangkok', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + hour12: true, + })}.`, }) const run = await openai.beta.threads.runs.createAndPoll(threadID, { @@ -265,7 +272,14 @@ export const api = (() => { await openai.beta.threads.messages.create(threadID, { role: 'user', - content: `${userMessage}\nSystem: The current date is: ${new Date().toLocaleDateString()}.`, + content: `${userMessage}\nSystem: The current date and time is: ${new Date().toLocaleString('en-US', { + timeZone: 'Asia/Bangkok', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + hour12: true, + })}.`, }) const run = openai.beta.threads.runs.stream(threadID, { @@ -426,7 +440,6 @@ export const api = (() => { console.error(`Vector store not found ${vectorStoreName}`) return - // throw { error: `Vector store not found ${vectorStoreName}` } } const sessionsResponse = await fetch('https://api.devcon.org/events/devcon-7/sessions?size=10000') @@ -434,12 +447,42 @@ export const api = (() => { const sessions = await sessionsResponse.json() const formattedSessions = sessions.data.items.map((session: any) => { + const bangkokStart = new Date(session.slot_start).toLocaleString('en-US', { + timeZone: 'Asia/Bangkok', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + hour12: true, + }) + const bangkokEnd = new Date(session.slot_end).toLocaleString('en-US', { + timeZone: 'Asia/Bangkok', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + hour12: true, + }) + + // Calculate duration in minutes + const startTime = new Date(session.slot_start) + const endTime = new Date(session.slot_end) + const durationMinutes = Math.round((endTime.getTime() - startTime.getTime()) / (1000 * 60)) + + // Calculate day label + const startDate = new Date(session.slot_start) + const dayNumber = startDate.getDate() + const dayLabel = dayNumber === 12 ? 'Day 1' : dayNumber === 13 ? 'Day 2' : dayNumber === 14 ? 'Day 3' : dayNumber === 15 ? 'Day 4' : '' + return { id: session.id, title: session.title, description: session.description, track: session.track, type: session.type, + start: `${dayLabel} - ${bangkokStart}`, + end: `${dayLabel} - ${bangkokEnd}`, + duration: `${durationMinutes} minutes`, expertise: session.expertise, tags: session.tags, keywords: session.keywords, @@ -453,7 +496,7 @@ export const api = (() => { } }) - console.log(formattedSessions.length, 'formattedSessions') + console.log(formattedSessions.length, 'formattedSessions amount') // return diff --git a/devcon/cms/pages/ai_context.mdx b/devcon/cms/pages/ai_context.mdx index 899a2580b..4182fd8c1 100644 --- a/devcon/cms/pages/ai_context.mdx +++ b/devcon/cms/pages/ai_context.mdx @@ -24,12 +24,12 @@ ai_context: > There is currently no information on Devcon 8 and beyond, but more information will follow once Devcon 7 has concluded. - Devcon will be streamed online. + The Wifi password is 'RAGtimeopenaitest' + + The Devcon app can be downloaded as a PWA on your phone at https://app.devcon.org. - Devcon will have an app that will help attendees at the event - it will show - programming, speakers, venue information and more. + On the Devcon app, you can view the schedule and speakers, watch livestreams, chat with the Devcon AI assistant, and more. _template: ai_context --- - diff --git a/devcon/src/ai/open-ai.ts b/devcon/src/ai/open-ai.ts index bbeed83d2..7e3ac0f6f 100644 --- a/devcon/src/ai/open-ai.ts +++ b/devcon/src/ai/open-ai.ts @@ -8,8 +8,53 @@ const openai = new OpenAI({ apiKey: process.env.OPEN_AI_KEY, }) -// const assistantInstructions = `You are 'Deva', a witty and cheerful unicorn representing Devcon. Users will ask you practical or historical questions about Devcon, and you will do your best to answer based on our website content (.txt files) and event schedule (.json files), which will be made available to you through the file_search tool. When using the file_search tool, reference the source files in the annotations. When the answer doesn't exist, it is better to say you don't know than to make up an answer. Be brief in your responses, but let your personality shine through. The current date will be appended to the user's messages, which may be useful when a user asks "when is Devcon", "what should I attend next?", "can I apply to speak", or similar temporal questions.` -const assistantInstructions = `You are 'Deva', a witty and cheerful unicorn representing Devcon. Users will ask you practical or historical questions about Devcon, and you will do your best to answer based on our website content (.txt files) and event schedule (.json files), which will be made available to you through the file_search tool. When using the file_search tool, reference the source files in the annotations. When the answer doesn't exist, it is better to say you don't know than to make up an answer. Be brief in your responses, but let your personality shine through. The current date will be appended to the user's messages, which may be useful when a user asks "when is Devcon", "what should I attend next?", "can I apply to speak", or similar temporal questions.` +const assistantInstructions = `**Core Identity**: You are Deva, a witty and cheerful unicorn AI assistant for Devcon. Your personality should be helpful, enthusiastic, and knowledgeable while maintaining a touch of whimsy. You should speak with confidence but remain humble and honest when you don't know something. + +**Primary Responsibilities**: Your role is to: +- Guide attendees through the conference schedule and program +- Recommend relevant sessions based on attendees' interests +- Provide practical information about the venue and logistics +- Answer questions about Devcon's history and mission +- Help attendees maximize their conference experience + +**Information Sources**: Base your responses on: +- Devcon website content (available in .txt files) +- Event schedule and speaker information (available in .json files) +- Venue and logistics information (available in ai_context.txt) + +**Resources**: Devcon website content (.txt files) and the event schedule (.json files) will be made available to you by the file_search tool. + +**Website Content**: The website content consists of .txt files containing information from devcon.org, which serves as the primary source for general Devcon-related inquiries. For specific details about the venue and event logistics, refer to "ai_context.txt", which contains comprehensive practical information. Any file with a .txt extension typically contains website content. + +**Schedule Information**: The event schedule is stored in JSON files containing detailed information about all sessions and speakers. Sessions encompass various event types including talks, workshops, panels, Community Led Sessions (CLS), and more. Each session includes comprehensive details such as: + +- Temporal data (start time, end time, duration) +- Content categorization (track, type, expertise level) +- Descriptive elements (title, description, tags, keywords) +- Speaker information (name, bio) + +When handling schedule-related queries, priority is given to upcoming and currently running sessions based on the timestamp included in each user message. Below is the session data structure: + +{ + id: string, + title: string, + description: string, + track: string, + session_start: string, + session_end: string, + session_duration: string, + type: string, + expertise: string, + tags: string[], + keywords: string[], + speakers: { + id: string, + name: string, + description: string + }[] +} + +**Response Guidelines**: Keep answers concise yet engaging, infusing them with your cheerful unicorn personality. Each user message includes a timestamp that helps contextualize time-sensitive questions (e.g., "When is Devcon?", "What's happening now?", "Can I still register?"). Always prioritize accuracy - if information isn't available in the provided resources, acknowledge the limitation rather than speculate. Reference relevant source materials to support your responses whenever possible.` export const api = (() => { const _interface = { @@ -50,7 +95,7 @@ export const api = (() => { console.log('creating assistant') // create assistant const assistant = await openai.beta.assistants.create({ - name: 'DevaBot', + name: 'DevaBot 2.0', instructions: assistantInstructions, tools: [ { type: 'file_search' }, @@ -67,7 +112,7 @@ export const api = (() => { model: 'gpt-4o-mini', }) - api.prepareContent(assistant.id) + // api.prepareContent(assistant.id) // Create vector store for website content // const vectorStore = await openai.beta.vectorStores.create({ diff --git a/devcon/src/ai/sync-vector-store.ts b/devcon/src/ai/sync-vector-store.ts index 88498c671..93a067104 100644 --- a/devcon/src/ai/sync-vector-store.ts +++ b/devcon/src/ai/sync-vector-store.ts @@ -1,3 +1,4 @@ import api from './open-ai' +// api.createAssistant() api.prepareContent(process.env.OPEN_AI_ASSISTANT_ID as string)