Tips for Setting Up Next.js 13 Route Handlers to Incorporate a Streaming API Endpoint via LangChain

I am currently working on establishing an API endpoint using the latest Route Handler feature in Nextjs 13. This particular API utilizes LangChain and streams the response directly to the frontend. When interacting with the OpenAI wrapper class, I make sure to include the Streaming parameter and define a callback function. This callback function is responsible for providing the stream in chunks (referred to as tokens), which are then transmitted to the frontend to display the AI's ongoing responses.

In the past, I successfully implemented this functionality using the traditional API route approach with the code snippet below:

import { OpenAI } from "langchain/llms/openai";

export default async function handler(req, res) {
  const chat = new OpenAI({
    modelName: "gpt-3.5-turbo",
    streaming: true,
    callbacks: [
      {
        handleLLMNewToken(token) {
          res.write(token);
        },
      },
    ],
  });

  await chat.call("Write me a song about sparkling water.");

  res.end();
}

Now, my goal is to adapt this code to the new Route Handler implementation, but unfortunately, I have not yet achieved success in doing so.

I have experimented with various strategies without any positive outcome.

For instance:

import { NextResponse } from "next/server";

import { OpenAI } from "langchain/llms/openai";

export const dynamic = "force-dynamic";
export const revalidate = true;

export async function GET(req, res) {
  const chat = new OpenAI({
    modelName: "gpt-3.5-turbo",
    streaming: true,
    callbacks: [
      {
        handleLLMNewToken(token) {
          // res.write(token);
          return new NextResponse.json(token);
        },
      },
    ],
  });

  await chat.call("Write me a song about sparkling water.");
}

It appears that there is no straightforward method to output or "write" the tokens to the response while they are being streamed to the Route Handler's response.

Any form of guidance or support on this matter would be immensely valuable and highly appreciated.

Answer №1

I believe I have found a potential solution.

In the Route Handler, I initiate a new stream object utilizing the TransformStream class. Subsequently, I feed the tokens into this stream object as they are produced. As the stream requires bytes for transfer, I utilize the TextEncoder to encode the token into a Uint8Array value.

Finally, I share the readable property of the stream in our API response. This method appears to work effectively, although it is slightly more intricate compared to the previous API route approach.

import { OpenAI } from "langchain/llms/openai";

export const dynamic = "force-dynamic";
export const revalidate = true;

async function runLLMChain() {
  // Initialize an encoder to convert token (string) into Uint8Array
  const encoder = new TextEncoder();

  // Create a TransformStream to write the response with generated tokens
  const stream = new TransformStream();
  const writer = stream.writable.getWriter();

  const chat = new OpenAI({
    modelName: "gpt-3.5-turbo",
    streaming: true,
    callbacks: [
      {
        async handleLLMNewToken(token) {
          await writer.ready;
          await writer.write(encoder.encode(`${token}`));
        },
        async handleLLMEnd() {
          await writer.ready;
          await writer.close();
        },
      },
    ],
  });
  chat.call("Write me a song about sparkling water.");

  // Return the readable stream
  return stream.readable;
}

export async function GET(req) {
  const stream = runLLMChain();
  return new Response(await stream);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with Magento site: Clicking on thumbnail photo does not update the large photo on mobile devices

As I navigate through a Magento site, I encounter a problem with the thumbnail images not reloading the larger image when clicked. Instead, the browser jumps to the top of the page and a hash symbol gets added to the URL. Based on this behavior, I suspect ...

AngularJS - Textarea not resetting content on ng-click event

Having an issue with my textarea. When attempting to clear it using ng-click, nothing happens... Can anyone provide assistance? Here is my code for testing: My app If you prefer to view it here: HTML : <div ng-controller="Ctrl1"> <d ...

Dynamic computed subcomponents in Vue.js are a powerful way to create flexible

Currently, I am facing a scenario where I need to create computed local subcomponents. Specifically, I am working on custom data grid row cell components. Here is an example of what I am trying to achieve: var DataGridRow = { props: ['columns&ap ...

What is the procedure in AngularJS to obtain an ID from a URL? My current approach involves utilizing Restangular for communication with REST APIs

I have been successfully using Restangular to retrieve data from the backend. The URLs I was hitting used to provide the data in the following format: For example, when I hit http://mysite/responses/, the responses were in the following structure: [ ...

Guide on utilizing map function in JavaScript and Vue to generate a fresh array

I am working on implementing a map method in JavaScript and Vue to generate a new array of objects while only including specific items in each object. I have designed a user interface with 2 checkboxes corresponding to 2 distinct objects: <div v-for ...

Guide to sending jQuery data back to main class in TypeScript

Hi everyone, I'm diving into the world of typescript and JQuery. I have a simple question. In my typescript class called DatePicker, I am calling a function. Here's a snippet of the code: Class DatePicker { private pickerData; public update( ...

Exploring Bootstrap datatables to search through nested table data with Codeigniter

I have implemented a table using bootstrap datatables and successfully enabled search functionality within the table. However, I have also included nested tables within each row of the main table. These nested tables are supposed to be displayed when clic ...

Tips for getting a plugin to function properly when the page is refreshed in Nuxt app

I am currently incorporating the vue GAPI plugin into my project. While it functions smoothly when navigating between pages, I encounter an error upon refreshing: vue-gapi.common.js?15fd:241 Uncaught (in promise) Error: gapi not initialized at GoogleAuth ...

When using NextJs with Material UI, manually refreshing the page may trigger a warning message stating: "Prop `className` did not match. Server: `MuiTypography-root MuiLink`."

In my Next.js project with Material UI, I am facing an issue where hot reloading works fine when I make changes and run the server. However, if I manually refresh the page, all the styles get messed up and I receive a warning saying: Warning: Prop classNam ...

How can I code a script to import JSON data into MongoDB database?

I have a JSON file named "data.json" that contains an array of people's names as shown below: "data": [ { { "name":"John", "age":30, } { "name":"Mark", "age":45, } } ] I am ...

Ways to verify and incorporate https:// in a URL for a MEAN Stack application

When extracting the URL from API data, my code looks like this: <div class="row copy-text"> <a href="{{copy.Url}}" target="_blank" style="text-decoration: underline !important;">{{copy.Title}}</a> </div> I am interested in ve ...

Turning a string retrieved from the element's data attribute into a JSON format

I am running into an issue with the code snippet below. It seems that $.parseJSON() is having trouble with single and double quotes. I'm stuck on finding a solution to this problem. Any help would be greatly appreciated! <div data-x='{"a":"1" ...

Encountering an issue where attempting to map through a property generated by the getStaticProps function results in a "cannot read properties

Greetings, I am fairly new to the world of Next.js and React, so kindly bear with me as I share my query. I have written some code within the getStaticProps function in Next.js to fetch data from an API and return it. The data seems to be processed correct ...

reveal a hidden div by sliding it during an onclick action

My PHP while loop code is as follows: while (...($...)){ $convid = $row['ID']; echo" <button onclick='getconvo($convid)'>open</button> <div class="convowrap"></div> "; } Here is the correspond ...

AngularJS: handling multiple asynchronous requests

When I make multiple ajax calls in my code, I noticed that the API is only reached after all the ajax calls have been executed. Below you can see the JavaScript code: function test = function(){ var entity = {}; entity.Number = 1; ...

Switching on the click functionality

I was able to successfully toggle a boolean variable along with some other options. However, I encountered an issue when trying to create another click function for a different button to set the boolean variable to false. Here is my code: let manageme ...

Is the NPM package not being imported? How exactly is it being utilized?

mediacms-vjs-plugin is a unique plugin designed for Video.js. The MediaCmsVjsPlugin.js source code begins with: import { version as VERSION } from '../package.json'; import 'mediacms-vjs-plugin-font-icons/dist/mediacms-vjs-icons.css'; ...

The process of handling state in React when it goes live in production

Currently, I am delving into the world of ReactJS as a novice. The intricacies of state management have captivated my interest. A pressing question has surfaced in my mind regarding this topic. Let's consider a scenario - I have developed a React appl ...

Organizing a Vue.js SPA project: Implementing Vuex store and API calls efficiently

Here is how I have organized the structure of my Vue app: components/ article/ AppList.vue common/ AppObserver.vue NoSSR.vue layout/ AppFooter.vue AppHeader.vue ui/ AppButton. ...

Writing in Node.js involves setting up a local DynamoDB for local development rather than running it in an actual Lambda

This straightforward aws.js script is used to execute dynamoDB operations locally. "use strict"; const AWS = require("aws-sdk"); AWS.config.dynamodb = { region: "eu-west-2", endpoint: "http://localhost:8000& ...