>  기사  >  웹 프론트엔드  >  OpenAI와 LangChain을 사용하여 강력한 챗봇 구축

OpenAI와 LangChain을 사용하여 강력한 챗봇 구축

王林
王林원래의
2024-09-12 10:33:021172검색

소개

챗봇은 사용자와 자동화된 상호작용을 제공하는 다양한 산업 분야에서 필수적인 도구입니다. 요즘 세상에 Chat GPT(또는 다른 AI 기반 챗봇)를 한 번 이상 시도하지 않은 사람은 없습니다. OpenAI의 GPT 모델과 LangChain 라이브러리를 사용하여 스트리밍 응답 시스템을 통해 세션을 처리하고 사용자 메시지를 처리하는 챗봇을 구축할 수 있습니다. 이후 게시물에서는 API와 통신하고 특정 작업에 특화된 에이전트를 만들 것입니다.

우리가 다룰 내용은 다음과 같습니다.

  • 미들웨어로 Express 서버를 설정합니다.
  • 챗봇 에이전트를 처리하기 위한 `AgentManager`를 생성합니다.
  • 챗봇 에이전트를 처리하기 위한 ChatAgent를 생성합니다.
  • 챗봇 응답을 실시간으로 사용자에게 스트리밍합니다.

환경 설정

먼저 몇 가지 주요 종속성이 필요합니다.

  • API 요청 처리를 위한 Express.
  • LangChain은 GPT 모델과 도구를 관리합니다.
  • GPT 모델 상호작용을 위한 OpenAI. 스폰 세션을 사용하고 챗봇과 상호 작용하려면 Open AI에서 토큰을 얻어야 합니다

종속성 설치

가장 먼저 할 일은 새 프로젝트를 초기화하고 사용할 필수 모듈을 설치하는 것입니다.

npm init -Y
npm install express langchain openai uuid class-validator class-transformer mutex

급행 경로 설정

시작하려면 두 가지 주요 경로를 정의하겠습니다.

첫 번째 경로는 새 채팅 세션을 생성하고, 두 번째 경로는 기존 세션에 메시지를 보냅니다.

router.post('/session', APIKeyMiddleware, createSession);
router.post('/session/:id/message', APIKeyMiddleware, postMessage);

APIKeyMiddleware는 인증된 요청만 이러한 경로에 액세스하도록 보장합니다. 귀하의 필요에 맞는 미들웨어를 구현할 수 있습니다.

에이전트 관리자 생성

채팅 상담원을 처리하기 위해 AgentManager 클래스를 생성하겠습니다. 이 클래스는 새 에이전트를 생성하고 활성 세션을 관리하는 역할을 담당하므로 이 클래스가 채팅을 담당할 에이전트를 포함하므로 API의 주요 진입점이라고 상상해 보세요. 첫 번째 사용자는 세션을 생성해야 하며 나중에 해당 세션이 채팅에 사용됩니다.

export class AgentManager {
    private __lock = new Mutex();
    private __agents: Map<string, AgentInstance> = new Map();

    async createAgent(authorization: string): Promise<string> {
        const uuid = uuidv4();
        const release = await this.__lock.acquire();
        try {
            this.__deleteExpiredAgentsLockless();
            let agent: ChatAgent | null = agent = new GeneralChatAgent(authorization);
            this.__agents.set(uuid, { agent, createdAt: Date.now() });
            return uuid;
        } finally {
            release();
        }
    }

    async getAgent(uuid: string): Promise<ChatAgent | null> {
        const release = await this.__lock.acquire();
        try {
            this.__deleteExpiredAgentsLockless();
            const agentInstance = this.__agents.get(uuid);
            return agentInstance ? agentInstance.agent : null;
        } finally {
            release();
        }
    }

    private __deleteExpiredAgentsLockless(): void {}
}

일반 에이전트 생성

이제 일반 채팅 에이전트를 만들어야 합니다. 이 에이전트는 인증이나 기타 필요한 매개변수를 가져오고 API와 통신할 수 있지만 지금은 기존 ChatAgent를 확장하겠습니다. 이 단계에서는 더 이상 아무것도 없습니다.

export class GeneralChatAgent extends ChatAgent {
    constructor() {
        super();
    }
}

createAgent 메소드는 에이전트를 초기화하고 프로세스를 잠근 후 고유한 세션 ID에 할당합니다. 에이전트는 지정된 세션 기간이 지나면 만료됩니다. 이는 __deleteExpiredAgentsLockless 메소드로 처리되지만 다음 반복에서는 이를 구현하므로 지금은 이를 방지할 수 있습니다.

세션 및 메시지 처리

다음으로 세션 생성 및 메시지 처리 경로를 정의해 보겠습니다.

export const createSession = async (req: Request, res: Response): Promise<void> => {
    const authorization = req.headers['authorization'] as string;
    try {
        const sessionId = await agentManager.createAgent(authorization, AgentType.WEB);
        res.json({ sessionId });
    } catch (err) {
        if (err instanceof Error) {
            res.status(400).json({ error: err.message });
        } else {
            res.status(500).json({ error: 'An unknown error occurred' });
        }
    }
}

export const postMessage = async (req: Request, res: Response): Promise<void> => {
    const { id } = req.params;
    const { message } = req.body;

    if (!id || !message) {
        return res.status(400).json({ error: 'Bad request. Missing session ID or message' });
    }

    try {
        const agent = await agentManager.getAgent(id);
        if (!agent) {
            return res.status(400).json({ error: `No agent found with id ${id}` });
        }

        const iterable = await agent.invoke(message);
        await streamResponse(res, iterable);
    } catch (err) {
        res.status(500).json({ error: err instanceof Error ? err.message : 'An unknown error occurred' });
    }
}

여기서 createSession은 새 세션을 설정하고 postMessage는 사용자의 메시지를 에이전트에 보냅니다. 세션이나 메시지가 제공되지 않으면 400 Bad Request 오류가 반환됩니다.
스트리밍 응답

이제 채팅 봇의 반응성과 대화형 느낌을 만드는 핵심은 응답 스트리밍입니다.

async invoke(input: string): Promise<AsyncIterable<Chunk>> {
    const release = await this.__lock.acquire();
    try {
        const tool = this.determineTool(input);
        if (tool) {
            const toolOutput = await tool.call(input);
            this.callbackQueue.enqueue({ type: ChunkType.TOKEN, value: toolOutput });
            this.callbackQueue.enqueue({ type: ChunkType.FINISH, value: '' });
        } else {
            await this.chat.invoke([new HumanMessage(input)], {
                callbacks: [
                    {
                        handleLLMNewToken: (token: string) => {
                            this.callbackQueue.enqueue({ type: ChunkType.TOKEN, value: token });
                        },
                        handleLLMEnd: () => {
                            this.callbackQueue.enqueue({ type: ChunkType.FINISH, value: '' });
                        },
                        handleLLMError: (error: Error) => {
                            this.callbackQueue.enqueue({ type: ChunkType.ERROR, value: error.message });
                        }
                    }
                ]
            });
        }
        return this.createAsyncIterable(this.callbackQueue);
    } finally {
        release();
    }
}

private createAsyncIterable(callbackQueue: AgentCallbackQueue): AsyncIterable<Chunk> {
    return {
        [Symbol.asyncIterator]: async function* () {
            let finished = false;
            while (!finished) {
                const chunk = await callbackQueue.dequeue();
                if (chunk) {
                    yield chunk;
                    if (chunk.type === ChunkType.FINISH || chunk.type === ChunkType.ERROR) {
                        finished = true;
                    }
                } else {
                    await new Promise(resolve => setTimeout(resolve, 100));
                }
            }
        }
    };
}

invoke 메서드에서 에이전트는 사용자의 입력을 처리하고 응답을 청크로 다시 스트리밍합니다. 각 청크는 모델의 토큰이거나 스트림의 끝을 나타내는 메시지입니다.

createAsyncIterable 메소드를 사용하면 이러한 청크를 하나씩 생성하고 클라이언트로 다시 스트리밍할 수 있습니다.

스트리밍 응답

결국 우리는 응답을 수신하면서 클라이언트에 스트리밍하고 싶습니다. 완료될 때까지 잠시 기다리지 않고 전체 응답을 반환하고 싶지 않습니다. 더 나은 해결책은 응답을 청크로 스트리밍하는 것입니다.

const delay = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));

export async function streamResponse(res: Response, iterable: AsyncIterable<Chunk>) {
    res.setHeader('Content-Type', 'application/x-ndjson');
    res.setHeader('Transfer-Encoding', 'chunked');

    try {
        let buffer = '';
        for await (const chunk of iterable) {
            switch (chunk.type) {
                case ChunkType.TOKEN:
                    buffer += chunk.value; 
                    res.write(buffer);
                    if (res.flush) res.flush();
                    buffer = '';
                    break;

                case ChunkType.ERROR:
                    console.error('Error chunk:', chunk.value);
                    if (!res.headersSent) {
                        res.status(500).json({ error: 'Streaming failed.' });
                    }
                    return;

                case ChunkType.FINISH:
                    if (buffer.trim()) {
                        res.write(`${buffer.trim()}\n`);
                    }
                    return;
            }
        }
    } catch (err) {
        console.error('Error during streaming:', err);
        if (!res.headersSent) {
            res.status(500).json({ error: 'Streaming failed.' });
        }
    } finally {
        res.end();
    }
}

결론

축하합니다! 이제 채팅 세션을 처리하고 클라이언트에게 응답을 스트리밍하는 기본 챗봇이 생겼습니다. 이 아키텍처는 추가 도구, 더 정교한 로직 또는 다양한 GPT 모델을 사용하여 쉽게 확장할 수 있지만 현재로서는 더 복잡한 챗봇을 위한 뼈대만 있습니다.

OpenAI의 강력한 언어 모델과 LangChain의 도구 관리를 사용하면 다양한 도메인에 대한 더욱 발전된 대화형 챗봇을 만들 수 있습니다. 챗봇 기능을 확장하고 원하는 방식으로 만들 수 있지만, 반면에 그럴 필요는 없습니다. Langchain을 사용하면 OpenAI를 사용하여 원하는 경우 훨씬 더 간단한 채팅 봇을 만들 수 있습니다.

더 많은 내용을 기대해 주세요. 다음 게시물에서는 우리가 만든 채팅 에이전트용 도구 구축에 대해 이야기하겠습니다.
즐거운 코딩하세요!

원본을 확인해주세요

Building a Powerful Chatbot with OpenAI and LangChain

OpenAI와 LangChain을 사용하여 강력한 챗봇 구축

이 게시물에서는 OpenAI와 LangChain을 사용하여 기본적이면서도 강력한 챗봇을 만드는 방법을 살펴보겠습니다.

bojanjagetic.com

위 내용은 OpenAI와 LangChain을 사용하여 강력한 챗봇 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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