LangChain cung cấp giao diện đơn giản để thực hiện các cuộc trò chuyện giữa con người và AI. Nó có thể được cấu hình dễ dàng để sử dụng BufferMemory , cho phép bạn lưu trữ lịch sử cuộc trò chuyện vào bộ nhớ. Điều này có thể thỏa đáng đối với một số trường hợp sử dụng, nhưng ứng dụng của bạn cũng có thể yêu cầu lịch sử trò chuyện tồn tại lâu dài. May mắn thay, việc hoán đổi cái này lấy phiên bản Upstash Redis cũng rất đơn giản.
LangChain cung cấp nhiều tích hợp cho Redis, bao gồm ioredis , node-redis và Upstash Redis. Vì ứng dụng khách Upstash Redis hoạt động thông qua REST nên bạn có thể sử dụng nó để tạo các ứng dụng sẵn sàng biên có thể triển khai cho Vercel, Cloudflare Workers hoặc bất kỳ môi trường không có máy chủ nào khác. Chúng tôi sẽ sử dụng nó để tạo một ứng dụng trò chuyện đơn giản có bộ nhớ tồn tại qua các phiên.
Bạn có thể tìm thấy mã nguồn đầy đủ cho bản demo này tại đây.
Điều kiện tiên quyết
- Cơ sở dữ liệu Upstash Redis
- Khóa API OpenAI
Bắt đầu
Tạo dự án
Chúng ta sẽ xây dựng một ứng dụng Next.js cơ bản bằng Vercel AI SDK để trình bày cách sử dụng LangChain với Upstash Redis. Để bắt đầu, hãy tạo ứng dụng Next.js mới:
npx create-next-app@latest
Điều này sẽ yêu cầu bạn chọn một vài tùy chọn dự án. Đối với hầu hết các ứng dụng, cài đặt mặc định sẽ hoạt động tốt. Vì mục đích của bản demo này, hãy đảm bảo bật TypeScript và app thư mục.
Cài đặt phụ thuộc
Sau khi tạo ứng dụng, bạn sẽ cần cài đặt một số phần phụ thuộc:
npm install ai langchain openai @upstash/redis
Mặc dù không bắt buộc nghiêm ngặt nhưng Vercel AI SDK sẽ giúp truyền phản hồi từ OpenAI đến giao diện Next.js của chúng tôi dễ dàng hơn. Chúng ta sẽ chỉ phải sử dụng @upstash/redis để tạo ứng dụng khách Redis—LangChain sẽ lo phần còn lại.
Đặt biến môi trường
Cuối cùng, chúng ta sẽ cần các biến môi trường sau đây từ các điều kiện tiên quyết trước đó. Hãy đảm bảo đặt tên chúng chính xác như được mô tả ở đây, vì nếu không chúng sẽ không được đọc tự động! Bạn có thể thêm chúng vào .env trong thư mục gốc của dự án mới của bạn:
UPSTASH_REDIS_REST_URL="https://********.upstash.io"
UPSTASH_REDIS_REST_TOKEN="********"
OPENAI_API_KEY="sk-********" Tạo ứng dụng trò chuyện cơ bản
Bạn sẽ nhận thấy rằng Next.js đã tạo một số tệp cho chúng tôi. Chúng tôi sẽ chỉ làm việc với một vài tệp trong app thư mục, vì vậy bạn có thể tiếp tục và xóa mọi thứ hiện có trong public và app .
Để bắt đầu, chúng ta sẽ tạo một app/layout.tsx cơ bản để chứa ứng dụng của chúng tôi:
import type { PropsWithChildren } from "react";
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Tiếp theo, chúng ta sẽ cần một biểu mẫu cơ bản có thông tin đầu vào để chấp nhận tin nhắn từ người dùng. Điều này có thể được thêm vào app/page.tsx của chúng tôi :
export default function Home() {
return (
<main>
<form>
<input placeholder="Enter a message..." />
<button type="submit">Send</button>
</form>
</main>
);
}

Vercel AI SDK xuất một hook hữu ích có tên useChat , điều này giúp việc tạo giao diện người dùng thông thường cho ứng dụng trò chuyện của chúng ta trở nên rất dễ dàng. Nó xử lý các tin nhắn trò chuyện trực tuyến và quản lý trạng thái đầu vào trò chuyện của chúng tôi. Để sử dụng hook, chúng ta cần cho React biết đây là thành phần máy khách bằng cách thêm "use client" chỉ thị ở đầu tập tin của chúng tôi. Sau đó, chúng ta có thể hủy cấu trúc một vài thuộc tính từ useChat móc:
messageslà một mảng các tin nhắn đã được gửi và nhận.inputlà giá trị hiện tại của trường đầu vào.handleInputChangelà hàm cập nhật giá trị đầu vào.handleSubmitlà một chức năng gửi tin nhắn đến điểm cuối của chúng tôi.
"use client";
import { useChat } from "ai/react";
export default function Home() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<main>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Enter a message..."
/>
<button type="submit">Send</button>
</form>
</main>
);
}
Trong nội bộ, useChat hook tự động thêm input đến messages khi handleSubmit được gọi, kích hoạt kết xuất lại để chúng ta không phải lo lắng về việc tự cập nhật giao diện người dùng. Nó cũng sẽ xóa trường đầu vào và kích hoạt lệnh gọi API đến điểm cuối được chỉ định. Theo mặc định, đây là /api/chat .
Cuối cùng, hãy kết xuất messages phía trên biểu mẫu của chúng tôi:
<main>
<section>
{messages.map((message) => (
<p key={message.id}>{message.content}</p>
))}
</section>
{/* snip */}
</main> Tạo điểm cuối API
Chúng ta có thể bắt đầu bằng cách tạo app/api/chat/route.ts tập tin để chứa điểm cuối của chúng tôi. Next.js sử dụng định tuyến dựa trên tệp cho các điểm cuối API cũng như các trang—đây là lý do tại sao cấu trúc thư mục cho tệp mới này khớp với điểm cuối mặc định, /api/chat , từ trước đó.
Vì chúng tôi đang sử dụng Upstash Redis nên điểm cuối của chúng tôi tương thích với biên. Chúng ta có thể chỉ định điều này bằng cách xuất const runtime = "edge" từ điểm cuối của chúng tôi. Trong chính điểm cuối, chúng ta có thể truy xuất messages trường mà useChat hook được điền cho chúng tôi. Điều này cho phép chúng tôi chuyển tin nhắn mới nhất tới LangChain:
import { type NextRequest } from "next/server";
import { LangChainStream, StreamingTextResponse } from "ai";
export const runtime = "edge";
export async function POST(req: NextRequest) {
const { messages } = await req.json();
const { stream, handlers } = LangChainStream();
const latestMessage = messages[messages.length - 1];
return new StreamingTextResponse(stream);
}
Giống như useChat từ trước, LangChainStream cũng trả về một số thuộc tính mà chúng ta có thể hủy cấu trúc.
streamlàReadableStreamcuối cùng sẽ chứa kết quả của quy trình LangChain.handlerslà một đối tượng chứa các hàm gọi lại LLM có thể được truyền tới LangChain.
Trước khi có thể tự triển khai chuỗi, chúng ta cần nhập một vài lớp bổ sung:
import { Redis } from "@upstash/redis";
import { ConversationChain } from "langchain/chains";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { BufferMemory } from "langchain/memory";
import { UpstashRedisChatMessageHistory } from "langchain/stores/message/upstash_redis";
Bây giờ chúng ta có thể tạo ứng dụng khách Redis và thiết lập bộ nhớ cho chuỗi của mình. Ở đây, chúng tôi tạo một ConversationChain mà chúng ta có thể gọi thay cho chính mô hình đó. Đó là một chuỗi tùy chỉnh tạo điều kiện thuận lợi cho việc tổ chức các cuộc trò chuyện giữa con người và AI. Chúng tôi có thể chuyển BaseMemory tùy chỉnh triển khai vào chuỗi, chuỗi này sẽ được sử dụng để lưu trữ và truy xuất tin nhắn. Trong trường hợp này, chúng tôi đang sử dụng BufferMemory với UpstashRedisChatMessageHistory để lưu trữ tin nhắn trong Upstash Redis:
// snip
const latestMessage = messages[messages.length - 1];
const memory = new BufferMemory({
chatHistory: new UpstashRedisChatMessageHistory({
sessionId: new Date().toLocaleDateString(),
client: Redis.fromEnv(),
}),
});
const model = new ChatOpenAI({
modelName: "gpt-3.5-turbo",
streaming: true,
});
const chain = new ConversationChain({ llm: model, memory });
// snip
Chúng tôi xây dựng ứng dụng khách Redis mới bằng Redis lớp được khám phá từ @upstash/redis . Nó cung cấp một phương thức để tải các biến môi trường một cách tự động một cách thuận tiện, phản ánh hành vi của ChatOpenAI . Miễn là bạn đặt tên chính xác cho các biến môi trường của mình, bạn sẽ không cần chuyển bất kỳ đối số bổ sung nào trong các lớp này.
Trong ứng dụng của mình, bạn có thể muốn sử dụng ID người dùng hoặc một số mã định danh duy nhất khác cho sessionId để đảm bảo rằng tin nhắn không được chia sẻ giữa những người dùng nhưng chúng tôi sẽ sử dụng ngày hiện tại vì mục đích minh họa này. UpstashRedisChatMessageHistory cung cấp nhiều tùy chọn cấu hình hơn như sessionTTL để đặt thời gian tồn tại của bộ đệm.
Điều quan trọng là phải bật streaming trên mô hình, vì điều này sẽ cho phép chúng tôi sử dụng handlers đã bị hủy cấu trúc của chúng tôi đối tượng từ trước để chuyển kết quả của chuỗi sang stream . Cuối cùng, chúng ta có thể gọi chuỗi, chuyển tin nhắn mới nhất và handlers đối tượng:
// snip
const chain = new ConversationChain({ llm: model, memory });
chain.call({
input: latestMessage.content,
callbacks: [handlers],
});
return new StreamingTextResponse(stream);
// snip
latestMessage của chúng tôi đối tượng trước đó được sử dụng làm lời nhắc cho LLM. Chúng tôi cũng chuyển handlers đối tượng với chuỗi, chuỗi này sẽ được sử dụng để chuyển kết quả sang stream .
Kết luận
Thế thôi! Bây giờ bạn có thể chạy ứng dụng của mình với npm run dev và bắt đầu trò chuyện với AI của bạn. Phản hồi sẽ tự động được truyền ngược lại ứng dụng khách mà chúng tôi đã tạo trước đó và lịch sử cuộc trò chuyện sẽ được lưu trữ trong Upstash Redis.

