This commit is contained in:
parent
ab01d11f31
commit
d22a1fbb6b
|
|
@ -11,6 +11,25 @@ import { Section } from '@/components/mpv2/section'
|
||||||
import { FollowupPanel } from '@/components/mpv2/followup-panel'
|
import { FollowupPanel } from '@/components/mpv2/followup-panel'
|
||||||
import { inquire, researcher, taskManager, querySuggestor } from '@/lib/agents'
|
import { inquire, researcher, taskManager, querySuggestor } from '@/lib/agents'
|
||||||
|
|
||||||
|
// ✅ 初始状态
|
||||||
|
const initialAIState: ExperimentalMessage[] = []
|
||||||
|
|
||||||
|
const initialUIState: {
|
||||||
|
id: number
|
||||||
|
isGenerating: StreamableValue<boolean>
|
||||||
|
component: React.ReactNode
|
||||||
|
}[] = []
|
||||||
|
|
||||||
|
// ✅ 先创建 AI
|
||||||
|
export const AI = createAI({
|
||||||
|
actions: {
|
||||||
|
submit
|
||||||
|
},
|
||||||
|
initialUIState,
|
||||||
|
initialAIState
|
||||||
|
})
|
||||||
|
|
||||||
|
// ✅ 再定义 submit,才能引用 AI
|
||||||
async function submit(formData?: FormData, skip?: boolean) {
|
async function submit(formData?: FormData, skip?: boolean) {
|
||||||
'use server'
|
'use server'
|
||||||
|
|
||||||
|
|
@ -19,7 +38,6 @@ async function submit(formData?: FormData, skip?: boolean) {
|
||||||
const isGenerating = createStreamableValue(true)
|
const isGenerating = createStreamableValue(true)
|
||||||
|
|
||||||
const messages: ExperimentalMessage[] = aiState.get() as any
|
const messages: ExperimentalMessage[] = aiState.get() as any
|
||||||
// Get the user input from the form data
|
|
||||||
const userInput = skip
|
const userInput = skip
|
||||||
? `{"action": "skip"}`
|
? `{"action": "skip"}`
|
||||||
: (formData?.get('input') as string)
|
: (formData?.get('input') as string)
|
||||||
|
|
@ -28,7 +46,7 @@ async function submit(formData?: FormData, skip?: boolean) {
|
||||||
: formData
|
: formData
|
||||||
? JSON.stringify(Object.fromEntries(formData))
|
? JSON.stringify(Object.fromEntries(formData))
|
||||||
: null
|
: null
|
||||||
// Add the user message to the state
|
|
||||||
if (content) {
|
if (content) {
|
||||||
const message = { role: 'user', content }
|
const message = { role: 'user', content }
|
||||||
messages.push(message as ExperimentalMessage)
|
messages.push(message as ExperimentalMessage)
|
||||||
|
|
@ -39,11 +57,9 @@ async function submit(formData?: FormData, skip?: boolean) {
|
||||||
uiStream.update(<Spinner />)
|
uiStream.update(<Spinner />)
|
||||||
|
|
||||||
let action: any = { object: { next: 'proceed' } }
|
let action: any = { object: { next: 'proceed' } }
|
||||||
// If the user skips the task, we proceed to the search
|
|
||||||
if (!skip) action = await taskManager(messages)
|
if (!skip) action = await taskManager(messages)
|
||||||
|
|
||||||
if (action.object.next === 'inquire') {
|
if (action.object.next === 'inquire') {
|
||||||
// Generate inquiry
|
|
||||||
const inquiry = await inquire(uiStream, messages)
|
const inquiry = await inquire(uiStream, messages)
|
||||||
|
|
||||||
uiStream.done()
|
uiStream.done()
|
||||||
|
|
@ -55,12 +71,10 @@ async function submit(formData?: FormData, skip?: boolean) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the answer
|
|
||||||
let answer = ''
|
let answer = ''
|
||||||
let errorOccurred = false
|
let errorOccurred = false
|
||||||
const streamText = createStreamableValue<string>()
|
const streamText = createStreamableValue<string>()
|
||||||
while (answer.length === 0) {
|
while (answer.length === 0) {
|
||||||
// Search the web and generate the answer
|
|
||||||
const { fullResponse, hasError } = await researcher(
|
const { fullResponse, hasError } = await researcher(
|
||||||
uiStream,
|
uiStream,
|
||||||
streamText,
|
streamText,
|
||||||
|
|
@ -72,10 +86,7 @@ async function submit(formData?: FormData, skip?: boolean) {
|
||||||
streamText.done()
|
streamText.done()
|
||||||
|
|
||||||
if (!errorOccurred) {
|
if (!errorOccurred) {
|
||||||
// Generate related queries
|
|
||||||
await querySuggestor(uiStream, messages)
|
await querySuggestor(uiStream, messages)
|
||||||
|
|
||||||
// Add follow-up panel
|
|
||||||
uiStream.append(
|
uiStream.append(
|
||||||
<Section title="Follow-up">
|
<Section title="Follow-up">
|
||||||
<FollowupPanel />
|
<FollowupPanel />
|
||||||
|
|
@ -96,47 +107,3 @@ async function submit(formData?: FormData, skip?: boolean) {
|
||||||
component: uiStream.value
|
component: uiStream.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the initial state of the AI. It can be any JSON object.
|
|
||||||
const initialAIState: {
|
|
||||||
role: 'user' | 'assistant' | 'system' | 'function' | 'tool'
|
|
||||||
content: string
|
|
||||||
id?: string
|
|
||||||
name?: string
|
|
||||||
}[] = []
|
|
||||||
|
|
||||||
// The initial UI state that the client will keep track of, which contains the message IDs and their UI nodes.
|
|
||||||
const initialUIState: {
|
|
||||||
id: number
|
|
||||||
isGenerating: StreamableValue<boolean>
|
|
||||||
component: React.ReactNode
|
|
||||||
}[] = []
|
|
||||||
|
|
||||||
// AI is a provider you wrap your application with so you can access AI and UI state in your components.
|
|
||||||
// export const AI = createAI({
|
|
||||||
// actions: {
|
|
||||||
// submit
|
|
||||||
// },
|
|
||||||
// // Each state can be any shape of object, but for chat applications
|
|
||||||
// // it makes sense to have an array of messages. Or you may prefer something like { id: number, messages: Message[] }
|
|
||||||
// initialUIState,
|
|
||||||
// initialAIState
|
|
||||||
// })
|
|
||||||
|
|
||||||
// ✅ 第一步:先创建 AI
|
|
||||||
const AI = createAI({
|
|
||||||
actions: { submit },
|
|
||||||
initialUIState,
|
|
||||||
initialAIState
|
|
||||||
})
|
|
||||||
|
|
||||||
// ✅ 第二步:解构出 Provider 和 hooks
|
|
||||||
export const {
|
|
||||||
AIProvider,
|
|
||||||
useUIState,
|
|
||||||
useAIState,
|
|
||||||
useActions
|
|
||||||
} = AI
|
|
||||||
|
|
||||||
// ✅ 第三步:导出 AI 给 getMutableAIState 用
|
|
||||||
export { AI }
|
|
||||||
Loading…
Reference in New Issue