Maison > Article > interface Web > Créer un chatbot puissant avec OpenAI et LangChain
Les chatbots sont des outils essentiels dans divers secteurs, offrant une interaction automatisée avec les utilisateurs. De nos jours, personne au monde n’a essayé au moins une fois Chat GPT (ou tout autre chatbot alimenté par l’IA). En utilisant les modèles GPT d'OpenAI et la bibliothèque LangChain, nous pouvons créer un chatbot qui gère les sessions et traite les messages des utilisateurs via un système de réponse en streaming, car dans un article ultérieur, nous communiquerons avec nos API et créerons des agents qui seront spécialisés pour certaines choses.
Voici ce que nous allons aborder :
Tout d'abord, nous avons besoin de quelques dépendances clés :
La première chose que nous faisons est d'initialiser le nouveau projet et d'installer les modules nécessaires que nous utiliserons.
npm init -Y npm install express langchain openai uuid class-validator class-transformer mutex
Pour commencer, nous définirons deux itinéraires principaux :
Le premier itinéraire créera une nouvelle session de discussion, tandis que le second enverra des messages à une session existante.
router.post('/session', APIKeyMiddleware, createSession); router.post('/session/:id/message', APIKeyMiddleware, postMessage);
L'APIKeyMiddleware garantit que seules les requêtes authentifiées accèdent à ces routes. Notez que vous pouvez implémenter un middleware adapté à vos besoins.
Nous allons créer une classe AgentManager pour gérer les agents de chat. Cette classe est responsable de la création de nouveaux agents et de la gestion des sessions actives, alors imaginez cette classe comme le point d'entrée principal de nos API car elle aura des agents qui seront responsables du chat. Le premier utilisateur devra créer une session et plus tard, cette session sera utilisée pour discuter.
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 {} }
Maintenant, nous devons créer un agent de chat général, qui obtiendra des paramètres avec, par exemple, l'authentification ou tout autre dont vous avez besoin et pourra communiquer avec l'API, mais pour l'instant, nous allons étendre le ChatAgent existant. et rien de plus pour cette étape.
export class GeneralChatAgent extends ChatAgent { constructor() { super(); } }
La méthode createAgent initialise un agent, verrouille le processus et lui attribue un ID de session unique. Les agents expirent après une durée de session spécifiée, qui est gérée par la méthode __deleteExpiredAgentsLockless mais nous l'implémenterons lors de la prochaine itération, vous pouvez l'éviter pour l'instant.
Ensuite, définissons nos itinéraires de création de session et de gestion des messages :
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' }); } }
Ici, createSession configure une nouvelle session et postMessage envoie le message d'un utilisateur à l'agent. Si aucune session ou aucun message n'est fourni, il renvoie une erreur 400 Bad Request.
Réponses en continu
Maintenant, la clé pour que notre chatbot se sente réactif et interactif : diffuser la réponse.
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)); } } } }; }
Dans la méthode d'invocation, l'agent traite les entrées de l'utilisateur et renvoie la réponse par morceaux. Chaque morceau est soit un jeton du modèle, soit un message indiquant la fin du flux.
La méthode createAsyncIterable nous permet de générer ces morceaux un par un et de les renvoyer au client.
En fin de compte, nous voulons diffuser la réponse au client au fur et à mesure que nous la recevons, nous ne voulons pas attendre un certain temps jusqu'à ce qu'elle soit terminée et renvoyer l'intégralité de la réponse, la meilleure solution consiste à diffuser la réponse en morceaux.
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(); } }
Félicitations ! Vous disposez désormais d'un chatbot de base qui gère les sessions de chat et transmet les réponses au client. Cette architecture peut être facilement étendue avec des outils supplémentaires, une logique plus sophistiquée ou différents modèles GPT, mais pour l'instant nous disposons du squelette d'un chatbot plus complexe.
En utilisant les puissants modèles de langage d'OpenAI et la gestion des outils de LangChain, vous pouvez créer des chatbots plus avancés et interactifs pour divers domaines. Vous pouvez étendre les capacités des chatbots et les créer de la manière que vous souhaitez, mais d'un autre côté, vous n'avez pas besoin de le faire. utilisez Langchain, vous pouvez utiliser OpenAI et créer un chatbot encore plus simple si vous préférez cette façon.
Restez à l'écoute pour en savoir plus, dans le prochain article, nous parlerons de la création d'outils pour l'agent de chat que nous avons créés
Bon codage !
N'hésitez pas à consulter le message original
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!