>  기사  >  웹 프론트엔드  >  Vercel AI SDK를 사용한 다중 병렬 AI 스트림

Vercel AI SDK를 사용한 다중 병렬 AI 스트림

WBOY
WBOY원래의
2024-07-17 17:43:02364검색

Multiple Parallel AI Streams with the Vercel AI SDK

Vercel AI SDK를 사용하면 OpenAI, Anthropic 등과 같은 LLM API와 쉽게 상호 작용하고 데이터를 스트리밍하여 웹 앱에 로드되는 즉시 표시할 수 있습니다. 이 문서에서는 여러 프롬프트를 동시에 실행하고 결과를 병렬로 확인하는 방법을 알아봅니다.

TL;DR: GitHub Repo가 출시되었습니다.

내가 왜 이 일을 하고 싶겠는가?

웹 앱에서 동시에 여러 데이터 가져오기 요청을 실행하려는 것은 드문 일이 아닙니다. 예를 들어, 가상의 블로깅 시스템에서 대시보드 인터페이스가 로드되면 사용자의 프로필 데이터, 해당 사용자가 작성한 게시물, 즐겨찾기에 추가한 다른 사용자의 게시물을 동시에 가져오고 싶을 수 있습니다.

동일한 대시보드가 ​​OpenAI에 동시에 요청했다면 OpenAI에 사용자 프로필 개선에 대한 팁을 요청하는 동시에 OpenAI의 최신 게시물에 대한 분석을 요청하고 싶을 수도 있습니다. 이론적으로는 원할 경우 수십 개의 AI 요청을 동시에 사용할 수 있으며(완전히 다른 플랫폼과 모델에서도) 정보를 분석하고 콘텐츠를 생성하며 모든 유형의 기타 작업을 동시에 수행할 수 있습니다.

설치 및 설정

여기에서 최종 결과가 포함된 GitHub 저장소를 복제할 수 있습니다.

처음부터 설정하려면:

  1. Next.js 앱 라우터 빠른 시작을 따르세요. 단지 기본 사항입니다. 앱을 생성하고, 종속성을 설치하고, OpenAI API 키를 추가하세요.
  2. shadcn/ui를 설치하고 설정합니다.

기본 UI 설정

모든 작업을 수행하는 주요 구성 요소에는 출력을 위한 양식과 일부 컨테이너가 포함됩니다. 몇 가지 기본 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>
      )
}

여기서 몇 가지 사항을 확인할 수 있습니다.

  • 양식
  • 로딩 애니메이션(및 표시/숨기기를 위한 isGenerating 플래그)
  • 날씨 콘텐츠 렌더링을 위한 컨테이너
  • 뉴스 콘텐츠 렌더링을 위한 컨테이너

지금은 이러한 값을 하드코딩할 수 있습니다. 모두 우리 스트림에서 삭제됩니다.

React Server 구성요소(RSC) 설정

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.
  );
}

시도해 볼 만한 다른 재미있는 것들

  • streamObject()를 사용하여 텍스트 대신 구조화된 JSON 데이터 스트리밍
  • 더 많은 것을 동시에 스트리밍
  • 다양한 API에서 동시에 스트리밍
  • 동일한 비교 메시지로 다양한 모델 스트리밍(예: Cohere, Anthropic, Gemini 등)
  • 서버에서 UI 스트리밍(createStreamableUI() 사용)

추가 자료 및 링크

  • 서버 작업 및 변형
  • Vercel AI SDK
  • streamText() API 문서
  • Next.js 앱 라우터 빠른 시작

위 내용은 Vercel AI SDK를 사용한 다중 병렬 AI 스트림의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.