Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat (ui/solid): add support for prepareRequestBody #4711

Merged
merged 6 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tidy-badgers-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ai-sdk/solid': patch
---

feat (ui/solid): add support for prepareRequestBody
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags: ['next', 'chat']

<Note type="warning">
`experimental_prepareRequestBody` is an experimental feature and only
available in React.
available in React and Solid.
</Note>

By default, `useChat` sends all messages as well as information from the request to the server.
Expand Down
4 changes: 2 additions & 2 deletions content/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,10 @@ Allows you to easily create a conversational user interface for your chatbot app
},
{
name: 'experimental_prepareRequestBody',
type: '(options: { messages: Message[]; requestData?: JSONValue; requestBody?: object, id: string }) => unknown',
type: '(options: { messages: UIMessage[]; requestData?: JSONValue; requestBody?: object, id: string }) => unknown',
isOptional: true,
description:
'Experimental (React only). When a function is provided, it will be used to prepare the request body for the chat API. This can be useful for customizing the request body based on the messages and data in the chat.',
'Experimental (React & Solid only). When a function is provided, it will be used to prepare the request body for the chat API. This can be useful for customizing the request body based on the messages and data in the chat.',
},
{
name: 'experimental_throttle',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { openai } from '@ai-sdk/openai';
import { streamText, Message } from 'ai';
import { APIEvent } from '@solidjs/start/server';

export const POST = async (event: APIEvent) => {
// Extract the `messages` from the body of the request
const { message } = await event.request.json();

// Implement your own logic here to add message history
const previousMessages: Message[] = [];
const messages = [...previousMessages, message];

// Call the language model
const result = streamText({
model: openai('gpt-4o-mini'),
messages,
async onFinish({ text, toolCalls, toolResults, usage, finishReason }) {
// Implement your own logic here, e.g. for storing messages
},
});

// Respond with the stream
return result.toDataStreamResponse();
};
78 changes: 78 additions & 0 deletions examples/solidstart-openai/src/routes/use-chat-request/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint-disable @next/next/no-img-element */
import { For } from 'solid-js';
import { useChat } from '@ai-sdk/solid';
import { createIdGenerator } from 'ai';

export default function Chat() {
const {
input,
messages,
handleInputChange,
handleSubmit,
isLoading,
error,
stop,
reload,
} = useChat({
api: '/api/use-chat-request',
sendExtraMessageFields: true,
generateId: createIdGenerator({ prefix: 'msgc', size: 16 }),

experimental_prepareRequestBody({ messages }) {
return {
message: messages[messages.length - 1],
};
},
});

return (
<div class="flex flex-col w-full max-w-md py-24 mx-auto stretch">
<div class="flex flex-col gap-2 p-2">
<For each={messages()}>
{message => (
<div class="whitespace-pre-wrap">
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.content}
</div>
)}
</For>
</div>

{isLoading() && (
<div class="mt-4 text-gray-500">
<div>Loading...</div>
<button
type="button"
class="px-4 py-2 mt-4 text-blue-500 border border-blue-500 rounded-md"
onClick={stop}
>
Stop
</button>
</div>
)}

{error() && (
<div class="mt-4">
<div class="text-red-500">An error occurred.</div>
<button
type="button"
class="px-4 py-2 mt-4 text-blue-500 border border-blue-500 rounded-md"
onClick={() => reload()}
>
Retry
</button>
</div>
)}

<form onSubmit={handleSubmit} class="fixed bottom-0 w-full max-w-md p-2">
<input
class="w-full p-2 mb-8 border border-gray-300 rounded shadow-xl"
value={input()}
placeholder="Say something..."
onInput={handleInputChange}
disabled={isLoading()}
/>
</form>
</div>
);
}
2 changes: 1 addition & 1 deletion packages/react/src/use-chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export function useChat({
*/
experimental_prepareRequestBody?: (options: {
id: string;
messages: Message[];
messages: UIMessage[];
requestData?: JSONValue;
requestBody?: object;
}) => unknown;
Expand Down
Loading
Loading