Use core messages spec (#337)
This commit is contained in:
parent
095550d4dc
commit
901e4ccec1
7 changed files with 231 additions and 107 deletions
|
|
@ -33,7 +33,7 @@ import {
|
|||
} from '@/lib/utils'
|
||||
import { saveChat } from '@/app/actions'
|
||||
import { SpinnerMessage, UserMessage } from '@/components/stocks/message'
|
||||
import { Chat } from '@/lib/types'
|
||||
import { Chat, Message } from '@/lib/types'
|
||||
import { auth } from '@/auth'
|
||||
|
||||
async function confirmPurchase(symbol: string, price: number, amount: number) {
|
||||
|
|
@ -85,18 +85,7 @@ async function confirmPurchase(symbol: string, price: number, amount: number) {
|
|||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages.slice(0, -1),
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'function',
|
||||
name: 'showStockPurchase',
|
||||
content: JSON.stringify({
|
||||
symbol,
|
||||
price,
|
||||
defaultAmount: amount,
|
||||
status: 'completed'
|
||||
})
|
||||
},
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'system',
|
||||
|
|
@ -208,15 +197,35 @@ async function submitUserMessage(content: string) {
|
|||
|
||||
await sleep(1000)
|
||||
|
||||
const toolCallId = nanoid()
|
||||
|
||||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'function',
|
||||
name: 'listStocks',
|
||||
content: JSON.stringify(stocks)
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolName: 'listStocks',
|
||||
toolCallId,
|
||||
args: { stocks }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'tool',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolName: 'listStocks',
|
||||
toolCallId,
|
||||
result: stocks
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
@ -249,15 +258,35 @@ async function submitUserMessage(content: string) {
|
|||
|
||||
await sleep(1000)
|
||||
|
||||
const toolCallId = nanoid()
|
||||
|
||||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'function',
|
||||
name: 'showStockPrice',
|
||||
content: JSON.stringify({ symbol, price, delta })
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolName: 'showStockPrice',
|
||||
toolCallId,
|
||||
args: { symbol, price, delta }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'tool',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolName: 'showStockPrice',
|
||||
toolCallId,
|
||||
result: { symbol, price, delta }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
@ -286,11 +315,42 @@ async function submitUserMessage(content: string) {
|
|||
)
|
||||
}),
|
||||
generate: async function* ({ symbol, price, numberOfShares = 100 }) {
|
||||
const toolCallId = nanoid()
|
||||
|
||||
if (numberOfShares <= 0 || numberOfShares > 1000) {
|
||||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolName: 'showStockPurchase',
|
||||
toolCallId,
|
||||
args: { symbol, price, numberOfShares }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'tool',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolName: 'showStockPurchase',
|
||||
toolCallId,
|
||||
result: {
|
||||
symbol,
|
||||
price,
|
||||
numberOfShares,
|
||||
status: 'expired'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'system',
|
||||
|
|
@ -300,37 +360,55 @@ async function submitUserMessage(content: string) {
|
|||
})
|
||||
|
||||
return <BotMessage content={'Invalid amount'} />
|
||||
} else {
|
||||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolName: 'showStockPurchase',
|
||||
toolCallId,
|
||||
args: { symbol, price, numberOfShares }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'tool',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolName: 'showStockPurchase',
|
||||
toolCallId,
|
||||
result: {
|
||||
symbol,
|
||||
price,
|
||||
numberOfShares
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
return (
|
||||
<BotCard>
|
||||
<Purchase
|
||||
props={{
|
||||
numberOfShares,
|
||||
symbol,
|
||||
price: +price,
|
||||
status: 'requires_action'
|
||||
}}
|
||||
/>
|
||||
</BotCard>
|
||||
)
|
||||
}
|
||||
|
||||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'function',
|
||||
name: 'showStockPurchase',
|
||||
content: JSON.stringify({
|
||||
symbol,
|
||||
price,
|
||||
numberOfShares
|
||||
})
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
return (
|
||||
<BotCard>
|
||||
<Purchase
|
||||
props={{
|
||||
numberOfShares,
|
||||
symbol,
|
||||
price: +price,
|
||||
status: 'requires_action'
|
||||
}}
|
||||
/>
|
||||
</BotCard>
|
||||
)
|
||||
}
|
||||
},
|
||||
getEvents: {
|
||||
|
|
@ -356,15 +434,35 @@ async function submitUserMessage(content: string) {
|
|||
|
||||
await sleep(1000)
|
||||
|
||||
const toolCallId = nanoid()
|
||||
|
||||
aiState.done({
|
||||
...aiState.get(),
|
||||
messages: [
|
||||
...aiState.get().messages,
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'function',
|
||||
name: 'getEvents',
|
||||
content: JSON.stringify(events)
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-call',
|
||||
toolName: 'getEvents',
|
||||
toolCallId,
|
||||
args: { events }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
role: 'tool',
|
||||
content: [
|
||||
{
|
||||
type: 'tool-result',
|
||||
toolName: 'getEvents',
|
||||
toolCallId,
|
||||
result: events
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
@ -385,13 +483,6 @@ async function submitUserMessage(content: string) {
|
|||
}
|
||||
}
|
||||
|
||||
export type Message = {
|
||||
role: 'user' | 'assistant' | 'system' | 'function' | 'data' | 'tool'
|
||||
content: string
|
||||
id: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
export type AIState = {
|
||||
chatId: string
|
||||
messages: Message[]
|
||||
|
|
@ -425,7 +516,7 @@ export const AI = createAI<AIState, UIState>({
|
|||
return
|
||||
}
|
||||
},
|
||||
onSetAIState: async ({ state, done }) => {
|
||||
onSetAIState: async ({ state }) => {
|
||||
'use server'
|
||||
|
||||
const session = await auth()
|
||||
|
|
@ -436,7 +527,9 @@ export const AI = createAI<AIState, UIState>({
|
|||
const createdAt = new Date()
|
||||
const userId = session.user.id as string
|
||||
const path = `/chat/${chatId}`
|
||||
const title = messages[0].content.substring(0, 100)
|
||||
|
||||
const firstMessageContent = messages[0].content as string
|
||||
const title = firstMessageContent.substring(0, 100)
|
||||
|
||||
const chat: Chat = {
|
||||
id: chatId,
|
||||
|
|
@ -460,28 +553,36 @@ export const getUIStateFromAIState = (aiState: Chat) => {
|
|||
.map((message, index) => ({
|
||||
id: `${aiState.chatId}-${index}`,
|
||||
display:
|
||||
message.role === 'function' ? (
|
||||
message.name === 'listStocks' ? (
|
||||
<BotCard>
|
||||
<Stocks props={JSON.parse(message.content)} />
|
||||
</BotCard>
|
||||
) : message.name === 'showStockPrice' ? (
|
||||
<BotCard>
|
||||
<Stock props={JSON.parse(message.content)} />
|
||||
</BotCard>
|
||||
) : message.name === 'showStockPurchase' ? (
|
||||
<BotCard>
|
||||
<Purchase props={JSON.parse(message.content)} />
|
||||
</BotCard>
|
||||
) : message.name === 'getEvents' ? (
|
||||
<BotCard>
|
||||
<Events props={JSON.parse(message.content)} />
|
||||
</BotCard>
|
||||
) : null
|
||||
message.role === 'tool' ? (
|
||||
message.content.map(tool => {
|
||||
return tool.toolName === 'listStocks' ? (
|
||||
<BotCard>
|
||||
{/* TODO: Infer types based on the tool result*/}
|
||||
{/* @ts-expect-error */}
|
||||
<Stocks props={tool.result} />
|
||||
</BotCard>
|
||||
) : tool.toolName === 'showStockPrice' ? (
|
||||
<BotCard>
|
||||
{/* @ts-expect-error */}
|
||||
<Stock props={tool.result} />
|
||||
</BotCard>
|
||||
) : tool.toolName === 'showStockPurchase' ? (
|
||||
<BotCard>
|
||||
{/* @ts-expect-error */}
|
||||
<Purchase props={tool.result} />
|
||||
</BotCard>
|
||||
) : tool.toolName === 'getEvents' ? (
|
||||
<BotCard>
|
||||
{/* @ts-expect-error */}
|
||||
<Events props={tool.result} />
|
||||
</BotCard>
|
||||
) : null
|
||||
})
|
||||
) : message.role === 'user' ? (
|
||||
<UserMessage>{message.content}</UserMessage>
|
||||
) : (
|
||||
<UserMessage>{message.content as string}</UserMessage>
|
||||
) : message.role === 'assistant' &&
|
||||
typeof message.content === 'string' ? (
|
||||
<BotMessage content={message.content} />
|
||||
)
|
||||
) : null
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue