Reputation: 5227
I'm using Vercel's AI SDK and its useChat utility hook in my Nuxt.js application to create a chat interface. I have different agents (e.g., General, Exercise, Cardiology) in a select menu, and I want to send the selected agent's value in the useChats()
's body
object with the API request to select the appropriate system prompts on the server side.
However, I'm facing an issue where the body
object is not updated reactively when the selected agent changes in the UI.
For some reason, this part of the code is not reactive on user select:
body: { agent: selectedAgent.value } // <---- for some reason this is not being updated on menu change
This causes the client to always send the same agent
as General
:
Full client-side details below:
<template>
<div class="text-center mt-6">
<select class="border border-2" v-model="selectedAgent" @change="changeAgent">
<option v-for="(agent, index) in agentsList" :key="index" :value="agent">{{ agent }}</option>
</select>
<div>
<div v-for="m in messages" key="m.id" >
{{ m.role === "user" ? "User: " : "AI: " }}
{{ m.content }}
</div>
<form @submit="handleSubmit">
<input v-model="input" />
</form>
</template>
<script>
import {useChat} from 'ai/vue'
const agentsList = ['General', 'Exercise', 'Cardiology']
const selectedAgent = ref(agentsList[0]); // Default agent
const { messages, input, handleSubmit } = useChat({
api: '/api/chat',
headers: { 'Content-Type': 'application/json' },
body: { agent: selectedAgent.value } // <---- for some reason this is not being updated on menu change
})
const changeAgent = (e) => {
selectedAgent.value = e.target.value;
// Clear the chat messages when the agent is changed
messages.value = []
};
</script>
The full code and demo:
Github repo: https://github.com/dosstx/nuxt-openai-demo
Live URL: https://main--chipper-snickerdoodle-13271f.netlify.app/
agent
value from the request body (server/api/chat.ts
):The output is:
import OpenAI from 'openai'
import { OpenAIStream } from 'ai'
import { CreateChatCompletionRequestMessage } from 'openai/resources/chat'
export default defineLazyEventHandler(async () => {
const apiKey = useRuntimeConfig().OPENAI_API_KEY;
if (!apiKey) throw new Error('Missing OpenAI API key')
const openai = new OpenAI({
apiKey: apiKey
})
const agents = {
Exercise: [
// ... system prompts for exercise agent
],
Cardiology: [
// ... system prompts for cardiology agent
],
General: [
// ... system prompts for General agent
]
// ... other agents
}
return defineEventHandler(async event => {
// Extract the `prompt` and `agent` from the body of the request
const { messages, agent } = (await readBody(event)) as {
messages: CreateChatCompletionRequestMessage[],
agent: keyof typeof agents // Expecting one of the keys from the agents object
}
// Select the agent's system prompts
const agentSystemMessages = agents[agent] || []
console.log('from server: ', messages, agent)
try {
// Create a chat completion request with the system prompts and messages
const request = {
model: 'gpt-3.5-turbo',
stream: true,
messages: [...agentSystemMessages, ...messages],
temperature: 0.2,
// top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
max_tokens: 400 // set this limit to length of assistants responses
};
// Send the request to OpenAI and get a response stream
const response = await openai.chat.completions.create(request);
// Return an OpenAIStream object that wraps the response stream
return OpenAIStream(response)
} catch (error) {
console.error(error);
// Return a 500 Internal Server Error response with a specific message
return {
status: 500,
body: { error: 'An error occurred while processing your request. Please try again later.' },
};
}
})
})
selectedAgent
value inside the changeAgent
function, but the body
object inside the useChat
hook does not reflect the updated value.How can I make the body
object inside the useChat
hook reactive to changes in the selected agent from the select menu? This value needs to be sent to the server to select the appropriate system prompts. Any insights or guidance would be greatly appreciated.
Upvotes: 1
Views: 510
Reputation: 222989
useChat
composable had design problem and provided no way to provide reactive body
in the options. Generally the solution that is idiomatic to Vue is to pass refs for reactive values in composable's arguments, this is the purpose that ref pattern serves.
Once this option has been provided, it's supposed to be used as:
...
const body = computed(() => ({ agent: selectedAgent.value }));
const { messages, input, handleSubmit } = useChat({
body,
...
})
Upvotes: 1