Rumah  >  Artikel  >  hujung hadapan web  >  Berbilang Strim AI Selari dengan Vercel AI SDK

Berbilang Strim AI Selari dengan Vercel AI SDK

WBOY
WBOYasal
2024-07-17 17:43:02422semak imbas

Multiple Parallel AI Streams with the Vercel AI SDK

Vercel AI SDK memudahkan untuk berinteraksi dengan API LLM seperti OpenAI, Anthropic dan sebagainya serta menstrim data supaya ia muncul dalam apl web anda dengan pantas semasa ia dimuatkan. Dalam artikel ini kita akan belajar cara menjalankan berbilang gesaan pada masa yang sama dan melihat keputusannya secara selari.

TL;DR: GitHub Repo ada di sini.

Mengapa saya mahu melakukan ini?

Adalah perkara biasa dalam apl web yang mahu menjalankan berbilang permintaan pengambilan data pada masa yang sama. Contohnya, dalam sistem blog hipotesis, apabila antara muka papan pemuka dimuatkan, kami mungkin ingin mengambil data profil pengguna, siaran yang mereka buat dan siaran pengguna lain yang mereka gemari semuanya pada masa yang sama.

Jika papan pemuka yang sama membuat permintaan kepada OpenAI pada masa yang sama, kami mungkin mahu meminta OpenAI secara serentak untuk mendapatkan petua tentang meningkatkan profil pengguna dan analisis siaran terbaharu mereka pada masa yang sama. Secara teori, kami boleh menggunakan berpuluh-puluh permintaan AI secara selari jika kami mahu (walaupun daripada platform dan model yang berbeza sama sekali), dan menganalisis maklumat, menjana kandungan dan melakukan semua jenis tugasan lain pada masa yang sama.

Pemasangan & Persediaan

Anda boleh mengklon repo GitHub yang mengandungi hasil akhir di sini.

Untuk menyediakan dari awal:

  1. Ikuti Mula Pantas Penghala Apl Next.js. Hanya perkara asas; jana apl, pasang kebergantungan dan tambah kunci API OpenAI anda.
  2. Pasang dan sediakan shadcn/ui.

Menyediakan UI asas

Komponen utama yang melakukan semua kerja akan mengandungi borang dan beberapa bekas untuk output. Menggunakan beberapa komponen asas shadcn-ui, borang akan kelihatan seperti ini:

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

Anda boleh melihat bahawa kami mempunyai beberapa perkara di sini:

  • Borang
  • Animasi memuatkan (dan bendera isGenerating untuk menunjukkan/menyembunyikannya)
  • Bekas untuk memaparkan kandungan cuaca
  • Bekas untuk memaparkan kandungan berita

Buat masa ini anda boleh mengekodkan nilai-nilai ini; mereka semua akan ditarik dari aliran kami.

Menyediakan Komponen Pelayan React (RSC)

Tindakan pelayan streamAnswer ialah perkara yang akan melakukan kerja mencipta dan mengemas kini strim kami.

Struktur tindakan adalah ini:

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,
  };
}

Menulis kod pelanggan

Pengendali onSubmit borang akan melakukan semua kerja di sini. Berikut ialah pecahan cara ia berfungsi:

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

Perkara lain yang menyeronokkan untuk dicuba

  • Menstrim data JSON berstruktur dan bukannya teks menggunakan streamObject()
  • Menstrim lebih banyak perkara secara selari
  • Menstrim daripada API berbeza sekaligus
  • Menstrim model berbeza dengan gesaan yang sama untuk perbandingan (cth., Cohere, Anthropic, Gemini, dll.)
  • Menstrim UI daripada pelayan (menggunakan createStreamableUI() )

Bacaan & pautan lanjut

  • Tindakan dan Mutasi Pelayan
  • Vercel AI SDK
  • streamText() dokumen API
  • Mula Pantas Penghala Apl Next.js

Atas ialah kandungan terperinci Berbilang Strim AI Selari dengan Vercel AI SDK. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn