Adattare i progetti esistenti di LLM per utilizzare LangChain

Adattare i progetti LLM esistenti per utilizzare LangChain.

Rifattorizzazione delle chiamate OpenAI in qualcosa di più potente con LangChain

Foto di JJ Ying su Unsplash

Congratulazioni, hai un proof-of-concept LLM funzionante di cui sei orgoglioso e pronto a mostrare al mondo! Forse hai utilizzato direttamente la libreria OpenAI o forse stai utilizzando un modello di base diverso e trasformatori HuggingFace. In ogni caso, hai lavorato sodo e stai cercando il prossimo passo. Ciò potrebbe significare la rifattorizzazione del codice, l’aggiunta del supporto per più modelli di base o l’aggiunta di funzionalità più avanzate come agenti o vector db. Ecco dove entra in gioco LangChain.

LangChain è un framework open source per lavorare con LLM e sviluppare applicazioni sopra di essi. Ha versioni sia in Python che in JavaScript e supporta più modelli di base e fornitori di LLM. Dispone anche di una serie di funzioni di utilità per gestire compiti comuni come il chunking dei documenti o l’interazione con i vector db. Convinto che valga la pena dare un’occhiata? Dai un’occhiata a questo eccellente articolo che è un ottimo punto di partenza per capire cosa è possibile fare:

Iniziare con LangChain: Guida per principianti alla creazione di applicazioni alimentate da LLM

Un tutorial di LangChain per costruire qualsiasi cosa con grandi modelli di linguaggio in Python

towardsdatascience.com

Questo articolo non si concentrerà sullo sviluppo da zero, ma sulla rifattorizzazione di un’applicazione esistente. Assumerà anche una certa comprensione di base di LangChain, ma ci saranno collegamenti alla documentazione pertinente. In particolare, mi concentrerò sulla rifattorizzazione di un progetto che ho scritto chiamato AdventureGPT, un agente autonomo per giocare al gioco di avventura testuale Colossal Cave Adventure del 1977. Se sei interessato a saperne di più su quel progetto, dai un’occhiata al mio articolo precedente su di esso:

AdventureGPT: Utilizzo di agenti supportati da LLM per giocare a giochi di avventura basati su testo

betterprogramming.pub

C’erano diverse aree in cui ero particolarmente interessato a fare la rifattorizzazione:

  1. Utilizzo di Chains al posto delle chiamate dirette a OpenAI
  2. Sostituzione delle utility di documento personalizzate per la gestione dei documenti/dati di LangChain

Ognuna di queste sarà affrontata a turno.

Iniziamo con cosa è una chain. Una chain è un metodo per combinare insieme diverse tecniche di manipolazione del prompt in un’unica unità che porta a una singola chiamata del modello di base. Una volta che si ha una chain funzionante, le chain possono essere combinate e utilizzate insieme per raggiungere compiti più complessi.

LangChain offre alcuni tipi di chain diversi, questo articolo si concentra su LLMChain e ConversationChain. LLMChain è il tipo di chain più semplice, che combina template di prompt con gli oggetti LLM supportati da LangChain. ConversationChains offrono flussi di lavoro conversazionali su misura come chatbot. Una delle principali caratteristiche di ConversationChain è la sua capacità di includere la memoria e archiviare automaticamente le parti passate della conversazione nel prompt.

I template di prompt sono una delle caratteristiche più potenti di LangChain, che ti permettono di includere variabili all’interno dei prompt. Quando si completa manualmente questa attività, si potrebbero utilizzare f-stringhe combinate con la concatenazione di stringhe e l’uso attento dei metodi __repr__ personalizzati per prendere i dati e inserirli in un prompt per un modello di base. Con il template di prompt, puoi formattare una stringa facendo l’escape delle variabili tra parentesi graffe. Questo è tutto ciò che devi fare.

A seconda del tipo di chain che stai creando, alcune variabili vengono impostate per te per impostazione predefinita, come la storia conversazionale o l’input dell’utente. Questo può comportare una certa complessità. In un prompt conversazionale tradizionale, ci sono messaggi dal sistema, dall’assistente AI e dall’utente o dall’umano. Quando si scrivono prompt a mano, si utilizzano etichette come “Sistema”, “Umano” e “AI” per etichettare ciascuno di questi messaggi per il prompt. LangChain può occuparsi di questo per te, consentendoti di utilizzare il metodo ChatPromptTemplate from_messages per specificare ogni messaggio come una lista di oggetti, consentendo un livello superiore di astrazione e l’inclusione automatica e la formattazione della cronologia.

Tutto questo potere ha un costo di complessità. Invece di adattare semplicemente i prompt con del testo, è necessario leggere l’estesa documentazione e possibilmente estendere il codice esistente per adattarlo a un caso d’uso specifico. Ad esempio, i prompt conversazionali tendono ad includere solo l’input dell’utente e la cronologia della conversazione come variabili. Tuttavia, volevo includere ulteriori contesti di gioco nel mio prompt per il mio PlayerAgent, che era responsabile dell’interazione con il mondo di gioco. Dopo aver aggiunto le variabili aggiuntive al mio prompt, sono stato accolto con l’errore seguente:

Ricevute variabili di input prompt inaspettate. Il prompt si aspetta ['completed_tasks', 'input', 'history', 'objective'], ma ha ricevuto ['history'] come input dalla memoria, e input come chiave di input normale. (type=value_error)

Ho fatto qualche ricerca e ho trovato un problema esistente su GitHub che descriveva esattamente il problema che stavo riscontrando, ma senza una soluzione chiara. Nonostante ciò, ho guardato il codice sorgente della classe ConversationChain e ho visto che c’era un metodo specifico utilizzato per convalidare che solo le variabili previste fossero passate come input. Ho creato una nuova classe sottoclasse della classe originale e ho sovrascritto il metodo. Con la mia classe CustomConversationChain in mano, dovevo specificare quale variabile doveva essere utilizzata da ConversationalMemoryBuffer per l’input dell’utente (o nel mio caso, del gioco) poiché c’erano più variabili di input. Questo è stato abbastanza semplice tramite la variabile di istanza input_key e voilà, tutto ha funzionato.

Una volta finito di convertire le mie chiamate OpenAI in catene, era ora di affrontare il modo in cui gestivo l’ingestione dei documenti. Come parte del mio ciclo di gioco, accettavo un percorso per un testo di una guida che veniva quindi convertito in compiti di gioco da completare da parte di PlayerAgent. Quando ho aggiunto questa funzionalità per la prima volta, ho semplicemente passato l’intera guida al prompt e ho sperato nel meglio. Man mano che ho trovato guide più sofisticate, ciò non era più possibile poiché la lunghezza delle guide superava la finestra di contesto consentita da OpenAI per ChatGPT. Pertanto, ho diviso il testo in pezzi di 500 token ed ho eseguito il prompt per convertire le guide di gioco in compiti di gioco più volte.

Quando ho detto che ho diviso il testo in circa 500 token, l’ho fatto in modo molto approssimativo, basandomi sul metodo split delle stringhe di Python per suddividere il testo in token (una approssimazione molto grossolana che non corrisponde a come la maggior parte dei LLM suddivide il testo) e poi ho trasformato l’array di token in una stringa tramite il metodo join, sempre della classe String. Anche se funziona, LangChain offre soluzioni migliori.

LangChain è in grado di suddividere il testo in modi diversi. Il più rilevante per la maggior parte delle persone è per token, poiché preserva il flusso del documento. C’è un’intera pagina di documentazione dedicata qui ai diversi metodi di suddivisione del testo per token. Sono supportate diverse librerie NLP per la tokenizzazione, ma ho scelto la soluzione nativa di LLM chiamata tiktoken, che è il primo metodo descritto. Sono bastate poche righe di codice per suddividere il testo in modo più efficace preservando gli spazi vuoti.

Questo è solo l’inizio delle preparazioni del documento che LangChain è in grado di fare. È anche in grado di convertire i pezzi di testo in un embedding di testo appropriato per l’archiviazione in un database vettoriale e successivamente per il recupero e l’inclusione nel prompt. Ho intenzione di farlo in futuro nel mio progetto, includendo un pezzo rilevante di una guida fornita a PlayerAgent.

LangChain è un potente framework open source che offre una serie di funzioni e utility per lavorare con LLM e sviluppare applicazioni su di essi. Che tu stia usando la libreria OpenAI o un diverso modello di base, LangChain offre supporto per più modelli di base e provider di LLM, rendendolo una scelta versatile per i tuoi progetti.

Anche se LangChain può introdurre una certa complessità rispetto alla gestione grezza dei prompt, offre numerosi vantaggi e semplifica l’interazione con i LLM. Standardizza il processo e fornisce strumenti utili per migliorare i tuoi prompt e massimizzare il potenziale del tuo LLM scelto.

Se sei interessato a vedere come LangChain può essere implementato in un progetto reale, puoi dare un’occhiata alla base di codice aggiornata per AdventureGPT, che utilizza LangChain per il refactoring e il miglioramento dell’app esistente.

GitHub – oaguy1/AdventureGPT su langchain

Contribuisci allo sviluppo di oaguy1/AdventureGPT creando un account su GitHub.

github.com

In generale, LangChain è una risorsa preziosa per gli sviluppatori che lavorano con LLM, fornendo un framework completo e una vasta gamma di funzionalità per migliorare le applicazioni basate su LLM. Esplora LangChain e sblocca tutto il potenziale dei tuoi progetti LLM!