vercel / ai

Build AI-powered applications with React, Svelte, Vue, and Solid
https://sdk.vercel.ai/docs
Other
8.62k stars 1.21k forks source link

All non OpenAI providers giving errors like Type 'GoogleGenerativeAILanguageModel' is not assignable to type 'LanguageModelV1'. #2015

Closed retired-Hurt closed 2 weeks ago

retired-Hurt commented 3 weeks ago

Description

All non-OpenAI providers are giving error like Type 'GoogleGenerativeAILanguageModel' is not assignable to type 'LanguageModelV1'...Steps to reproduce

Clone the repo (https://github.com/vercel/ai-chatbot) to local On lib --> chat --> actions.tsx write following code import { google } from '@ai-sdk/google';

Replace the code model: openai('gpt-3.5-turbo'), with the code google('models/gemini-pro'), and it shows the above compilation error on vscode. I have tried this with other providers like mistral, anthropic and all of them give the same error. However the groq provider doesn't give the same error as it uses the OpenAI provider.

Is there an underlying problem with the SDK or is there something I am missing here?

Code example

import 'server-only'

import { createAI, createStreamableUI, getMutableAIState, getAIState, streamUI, createStreamableValue } from 'ai/rsc' import { openai } from '@ai-sdk/openai' import { vertex } from '@ai-sdk/google-vertex';

import { spinner, BotCard, BotMessage, SystemMessage, Stock, Purchase } from '@/components/stocks'

import { z } from 'zod' import { EventsSkeleton } from '@/components/stocks/events-skeleton' import { Events } from '@/components/stocks/events' import { StocksSkeleton } from '@/components/stocks/stocks-skeleton' import { Stocks } from '@/components/stocks/stocks' import { StockSkeleton } from '@/components/stocks/stock-skeleton' import { formatNumber, runAsyncFnWithoutBlocking, sleep, nanoid } from '@/lib/utils' import { saveChat } from '@/app/actions' import { SpinnerMessage, UserMessage } from '@/components/stocks/message' import { Chat, Message } from '@/lib/types' import { auth } from '@/auth' import { streamText } from 'ai';

async function confirmPurchase(symbol: string, price: number, amount: number) { 'use server'

const aiState = getMutableAIState()

const purchasing = createStreamableUI(

{spinner}

Purchasing {amount} ${symbol}...

)

const systemMessage = createStreamableUI(null)

runAsyncFnWithoutBlocking(async () => { await sleep(1000)

purchasing.update(
  <div className="inline-flex items-start gap-1 md:items-center">
    {spinner}
    <p className="mb-2">
      Purchasing {amount} ${symbol}... working on it...
    </p>
  </div>
)

await sleep(1000)

purchasing.done(
  <div>
    <p className="mb-2">
      You have successfully purchased {amount} ${symbol}. Total cost:{' '}
      {formatNumber(amount * price)}
    </p>
  </div>
)

systemMessage.done(
  <SystemMessage>
    You have purchased {amount} shares of {symbol} at ${price}. Total cost ={' '}
    {formatNumber(amount * price)}.
  </SystemMessage>
)

aiState.done({
  ...aiState.get(),
  messages: [
    ...aiState.get().messages,
    {
      id: nanoid(),
      role: 'system',
      content: `[User has purchased ${amount} shares of ${symbol} at ${price}. Total cost = ${amount * price
        }]`
    }
  ]
})

})

return { purchasingUI: purchasing.value, newMessage: { id: nanoid(), display: systemMessage.value } } }

async function submitUserMessage(content: string) { 'use server'

const aiState = getMutableAIState()

aiState.update({ ...aiState.get(), messages: [ ...aiState.get().messages, { id: nanoid(), role: 'user', content } ] })

let textStream: undefined | ReturnType<typeof createStreamableValue> let textNode: undefined | React.ReactNode

const result = await streamUI({ model: openai('gpt-3.5-turbo'), //model: vertex('models/gemini-pro'), initial: , system: Hi, messages: [ ...aiState.get().messages.map((message: any) => ({ role: message.role, content: message.content, name: message.name })) ], text: ({ content, done, delta }) => { if (!textStream) { textStream = createStreamableValue('') textNode = }

  if (done) {
    textStream.done()
    aiState.done({
      ...aiState.get(),
      messages: [
        ...aiState.get().messages,
        {
          id: nanoid(),
          role: 'assistant',
          content
        }
      ]
    })
  } else {
    textStream.update(delta)
  }

  return textNode
},
tools: {},
//   listStocks: {
//     description: 'List three imaginary stocks that are trending.',
//     parameters: z.object({
//       stocks: z.array(
//         z.object({
//           symbol: z.string().describe('The symbol of the stock'),
//           price: z.number().describe('The price of the stock'),
//           delta: z.number().describe('The change in price of the stock')
//         })
//       )
//     }),
//     generate: async function* ({ stocks }) {
//       yield (
//         <BotCard>
//           <StocksSkeleton />
//         </BotCard>
//       )

//       await sleep(1000)

//       const toolCallId = nanoid()

//       aiState.done({
//         ...aiState.get(),
//         messages: [
//           ...aiState.get().messages,
//           {
//             id: nanoid(),
//             role: 'assistant',
//             content: [
//               {
//                 type: 'tool-call',
//                 toolName: 'listStocks',
//                 toolCallId,
//                 args: { stocks }
//               }
//             ]
//           },
//           {
//             id: nanoid(),
//             role: 'tool',
//             content: [
//               {
//                 type: 'tool-result',
//                 toolName: 'listStocks',
//                 toolCallId,
//                 result: stocks
//               }
//             ]
//           }
//         ]
//       })

//       return (
//         <BotCard>
//           <Stocks props={stocks} />
//         </BotCard>
//       )
//     }
//   },
//   showStockPrice: {
//     description:
//       'Get the current stock price of a given stock or currency. Use this to show the price to the user.',
//     parameters: z.object({
//       symbol: z
//         .string()
//         .describe(
//           'The name or symbol of the stock or currency. e.g. DOGE/AAPL/USD.'
//         ),
//       price: z.number().describe('The price of the stock.'),
//       delta: z.number().describe('The change in price of the stock')
//     }),
//     generate: async function* ({ symbol, price, delta }) {
//       yield (
//         <BotCard>
//           <StockSkeleton />
//         </BotCard>
//       )

//       await sleep(1000)

//       const toolCallId = nanoid()

//       aiState.done({
//         ...aiState.get(),
//         messages: [
//           ...aiState.get().messages,
//           {
//             id: nanoid(),
//             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 }
//               }
//             ]
//           }
//         ]
//       })

//       return (
//         <BotCard>
//           <Stock props={{ symbol, price, delta }} />
//         </BotCard>
//       )
//     }
//   },
//   showStockPurchase: {
//     description:
//       'Show price and the UI to purchase a stock or currency. Use this if the user wants to purchase a stock or currency.',
//     parameters: z.object({
//       symbol: z
//         .string()
//         .describe(
//           'The name or symbol of the stock or currency. e.g. DOGE/AAPL/USD.'
//         ),
//       price: z.number().describe('The price of the stock.'),
//       numberOfShares: z
//         .number()
//         .describe(
//           'The **number of shares** for a stock or currency to purchase. Can be optional if the user did not specify it.'
//         )
//     }),
//     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',
//               content: `[User has selected an invalid amount]`
//             }
//           ]
//         })

//         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>
//         )
//       }
//     }
//   },
//   getEvents: {
//     description:
//       'List funny imaginary events between user highlighted dates that describe stock activity.',
//     parameters: z.object({
//       events: z.array(
//         z.object({
//           date: z
//             .string()
//             .describe('The date of the event, in ISO-8601 format'),
//           headline: z.string().describe('The headline of the event'),
//           description: z.string().describe('The description of the event')
//         })
//       )
//     }),
//     generate: async function* ({ events }) {
//       yield (
//         <BotCard>
//           <EventsSkeleton />
//         </BotCard>
//       )

//       await sleep(1000)

//       const toolCallId = nanoid()

//       aiState.done({
//         ...aiState.get(),
//         messages: [
//           ...aiState.get().messages,
//           {
//             id: nanoid(),
//             role: 'assistant',
//             content: [
//               {
//                 type: 'tool-call',
//                 toolName: 'getEvents',
//                 toolCallId,
//                 args: { events }
//               }
//             ]
//           },
//           {
//             id: nanoid(),
//             role: 'tool',
//             content: [
//               {
//                 type: 'tool-result',
//                 toolName: 'getEvents',
//                 toolCallId,
//                 result: events
//               }
//             ]
//           }
//         ]
//       })

//       return (
//         <BotCard>
//           <Events props={events} />
//         </BotCard>
//       )
//     }
//   }
// }

},)

return { id: nanoid(), display: result.value } }

export type AIState = { chatId: string messages: Message[] }

export type UIState = { id: string display: React.ReactNode }[]

export const AI = createAI<AIState, UIState>({ actions: { submitUserMessage, confirmPurchase }, initialUIState: [], initialAIState: { chatId: nanoid(), messages: [] }, onGetUIState: async () => { 'use server'

const session = await auth()

if (session && session.user) {
  const aiState = getAIState()

  if (aiState) {
    const uiState = getUIStateFromAIState(aiState)
    return uiState
  }
} else {
  return
}

}, onSetAIState: async ({ state }) => { 'use server'

const session = await auth()

if (session && session.user) {
  const { chatId, messages } = state

  const createdAt = new Date()
  const userId = session.user.id as string
  const path = `/chat/${chatId}`

  const firstMessageContent = messages[0].content as string
  const title = firstMessageContent.substring(0, 100)

  const chat: Chat = {
    id: chatId,
    title,
    userId,
    createdAt,
    messages,
    path
  }

  await saveChat(chat)
} else {
  return
}

} })

export const getUIStateFromAIState = (aiState: Chat) => { return aiState.messages .filter(message => message.role !== 'system') .map((message, index) => ({ id: ${aiState.chatId}-${index}, display: message.role === 'tool' ? ( message.content.map(tool => { return tool.toolName === 'listStocks' ? (

{/* TODO: Infer types based on the tool result*/} {/* @ts-expect-error */}
        ) : 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 as string}</UserMessage>
    ) : message.role === 'assistant' &&
      typeof message.content === 'string' ? (
      <BotMessage content={message.content} />
    ) : null
}))

}

Additional context

I suspect this must be something related to the underlying framework as all I am doing is replacing the openAI provider with google provider of Vercel

lgrammel commented 3 weeks ago

Have you updated the provider to the latest version?

retired-Hurt commented 3 weeks ago

Have you updated the provider to the latest version?

I think I know what's happening here. The openAI provider (@ai-sdk/openai": "^0.0.9) is bringing in the dependencies "@ai-sdk/provider": "0.0.3". However the non-openAI providers are bringing in the dependencies "@ai-sdk/provider@0.0.10". So my pnpm-lock.yaml file looks like below

` '@ai-sdk/provider@0.0.10': resolution: {integrity: sha512-NzkrtREQpHID1cTqY/C4CI30PVOaXWKYytDR2EcytmFgnP7Z6+CrGIA/YCnNhYAuUm6Nx+nGpRL/Hmyrv7NYzg==} engines: {node: '>=18'}

'@ai-sdk/provider@0.0.3': resolution: {integrity: sha512-0B8P6VZpJ6F9yS9BpmJBYSqIaIfeRtL5tD5SP+qgR8y0pPwalIbRMUFiLz9YUT6g70MJsCLpm/2/fX3cfAYCJw==} engines: {node: '>=18'}`

And somehow these 2 are conflicting inside vscode. Have to see how to bypass the same

lgrammel commented 2 weeks ago

Can you update the openai provider to ^0.0.31?

retired-Hurt commented 2 weeks ago

Can you update the openai provider to ^0.0.31?

Here is how I fixed it. I removed all node_modules, did fresh installations on all the modules, updated openai to ^4.51.0 and things seem to be working fine even with openai provider at ^0.0.9.

But now, I'm getting a different error on the line const uiState = getUIStateFromAIState(aiState) with the error as 'Argument of type 'Readonly' is not assignable to parameter of type 'Chat'. Type 'Readonly' is missing the following properties from type 'Chat': id, title, createdAt, userId, and 2 more.'. Looks like some underlying implementation has changed for the AI providers returning any type instead of Chat. Need to figure out what's the issue behind it

retired-Hurt commented 2 weeks ago

Closing the issue as getting the right modules helped fix the error

mattwkelly commented 2 weeks ago

I'm hitting this same issue. How did you resolve it exactly? Thanks

retired-Hurt commented 2 weeks ago

Is the above fix not working? Try with the following

@ai-sdk/openai": "^0.0.9 ai": "^3.2.0", Do not install openai

mattwkelly commented 2 weeks ago

Running npm update on ai and ai-sdk fixed it for me. Thanks