Vercel AI SDK를 사용하면 OpenAI, Anthropic 등과 같은 LLM API와 쉽게 상호 작용하고 데이터를 스트리밍하여 웹 앱에 로드되는 즉시 표시할 수 있습니다. 이 문서에서는 여러 프롬프트를 동시에 실행하고 결과를 병렬로 확인하는 방법을 알아봅니다.
TL;DR: GitHub Repo가 출시되었습니다.
웹 앱에서 동시에 여러 데이터 가져오기 요청을 실행하려는 것은 드문 일이 아닙니다. 예를 들어, 가상의 블로깅 시스템에서 대시보드 인터페이스가 로드되면 사용자의 프로필 데이터, 해당 사용자가 작성한 게시물, 즐겨찾기에 추가한 다른 사용자의 게시물을 동시에 가져오고 싶을 수 있습니다.
동일한 대시보드가 OpenAI에 동시에 요청했다면 OpenAI에 사용자 프로필 개선에 대한 팁을 요청하는 동시에 OpenAI의 최신 게시물에 대한 분석을 요청하고 싶을 수도 있습니다. 이론적으로는 원할 경우 수십 개의 AI 요청을 동시에 사용할 수 있으며(완전히 다른 플랫폼과 모델에서도) 정보를 분석하고 콘텐츠를 생성하며 모든 유형의 기타 작업을 동시에 수행할 수 있습니다.
여기에서 최종 결과가 포함된 GitHub 저장소를 복제할 수 있습니다.
처음부터 설정하려면:
모든 작업을 수행하는 주요 구성 요소에는 출력을 위한 양식과 일부 컨테이너가 포함됩니다. 몇 가지 기본 shadcn-ui 구성 요소를 사용하면 형식은 다음과 같습니다.
export function GenerationForm() { // State and other info will be defined here... return ( <form onSubmit={onSubmit} className="flex flex-col gap-3 w-full"> <div className="inline-block mb-4 w-full flex flex-row gap-1"> <Button type="submit">Generate News & Weather</Button> </div> {isGenerating ? ( <div className="flex flex-row w-full justify-center items-center p-4 transition-all"> <Spinner className="h-6 w-6 text-slate-900" /> </div> ) : null} <h3 className="font-bold">Historical Weather</h3> <div className="mt-4 mb-8 p-4 rounded-md shadow-md bg-blue-100"> {weather ? weather : null} </div> <h4 className="font-bold">Historical News</h4> <div className="mt-4 p-4 rounded-md shadow-md bg-green-100">{news ? news : null}</div> </form> ) }
여기서 몇 가지 사항을 확인할 수 있습니다.
지금은 이러한 값을 하드코딩할 수 있습니다. 모두 우리 스트림에서 삭제됩니다.
streamAnswer 서버 작업은 스트림을 생성하고 업데이트하는 작업을 수행합니다.
액션의 구조는 다음과 같습니다.
export async function streamAnswer(question: string) { // Booleans for indicating whether each stream is currently streaming const isGeneratingStream1 = createStreamableValue(true); const isGeneratingStream2 = createStreamableValue(true); // The current stream values const weatherStream = createStreamableValue(""); const newsStream = createStreamableValue(""); // Create the first stream. Notice that we don't use await here, so that we // don't block the rest of this function from running. streamText({ // ... params, including the LLM prompt }).then(async (result) => { // Read from the async iterator. Set the stream value to each new word // received. for await (const value of result.textStream) { weatherStream.update(value || ""); } } finally { // Set isGenerating to false, and close that stream. isGeneratingStream1.update(false); isGeneratingStream1.done(); // Close the given stream so the request doesn't hang. weatherStream.done(); } }); // Same thing for the second stream. streamText({ // ... params }).then(async (result) => { // ... }) // Return any streams we want to read on the client. return { isGeneratingStream1: isGeneratingStream1.value, isGeneratingStream2: isGeneratingStream2.value, weatherStream: weatherStream.value, newsStream: newsStream.value, }; }
양식의 onSubmit 핸들러가 여기서 모든 작업을 수행합니다. 작동 방식은 다음과 같습니다.
"use client"; import { SyntheticEvent, useState } from "react"; import { Button } from "./ui/button"; import { readStreamableValue, useUIState } from "ai/rsc"; import { streamAnswer } from "@/app/actions"; import { Spinner } from "./svgs/Spinner"; export function GenerationForm() { // State for loading flags const [isGeneratingStream1, setIsGeneratingStream1] = useState<boolean>(false); const [isGeneratingStream2, setIsGeneratingStream2] = useState<boolean>(false); // State for the LLM output streams const [weather, setWeather] = useState<string>(""); const [news, setNews] = useState<string>(""); // We'll hide the loader when both streams are done. const isGenerating = isGeneratingStream1 || isGeneratingStream2; async function onSubmit(e: SyntheticEvent) { e.preventDefault(); // Clear previous results. setNews(""); setWeather(""); // Call the server action. The returned object will have all the streams in it. const result = await streamAnswer(question); // Translate each stream into an async iterator so we can loop through // the values as they are generated. const isGeneratingStream1 = readStreamableValue(result.isGeneratingStream1); const isGeneratingStream2 = readStreamableValue(result.isGeneratingStream2); const weatherStream = readStreamableValue(result.weatherStream); const newsStream = readStreamableValue(result.newsStream); // Iterate through each stream, putting its values into state one by one. // Notice the IIFEs again! As on the server, these allow us to prevent blocking // the function, so that we can run these iterators in parallel. (async () => { for await (const value of isGeneratingStream1) { if (value != null) { setIsGeneratingStream1(value); } } })(); (async () => { for await (const value of isGeneratingStream2) { if (value != null) { setIsGeneratingStream2(value); } } })(); (async () => { for await (const value of weatherStream) { setWeather((existing) => (existing + value) as string); } })(); (async () => { for await (const value of newsStream) { setNews((existing) => (existing + value) as string); } })(); } return ( // ... The form code from before. ); }
위 내용은 Vercel AI SDK를 사용한 다중 병렬 AI 스트림의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!