GoodAI-LTM équipe les agents d'une mémoire à long terme basée sur du texte en combinant des composants essentiels tels que des modèles d'intégration de texte, le reclassement, les bases de données vectorielles, la réécriture de mémoire et de requêtes, le découpage automatique, les métadonnées de fragments et l'expansion de fragments. Ce package est spécifiquement conçu pour offrir un flux de mémoire centré sur le dialogue pour les agents sociaux.
De plus, GoodAI-LTM comprend un composant d'agent conversationnel (LTMAgent) pour une intégration transparente dans les applications basées sur Python.
pip install goodai-ltm
Appelez la méthode reply
d'une instance LTMAgent
pour obtenir une réponse de l'agent.
from goodai.ltm.agent import LTMAgent
agent = LTMAgent(model="gpt-3.5-turbo")
response = agent.reply("What can you tell me about yourself?")
print(response)
Le paramètre model
peut être le nom de n'importe quel modèle pris en charge par la bibliothèque litellm.
Un historique de session est conservé automatiquement par l'agent. Si vous souhaitez démarrer une nouvelle session, appelez la méthode new_session
.
agent.new_session()
print(f"Number of messages in session: {len(agent.session.message_history)}")
L'agent dispose d'une mémoire conversationnelle mais également d'une base de connaissances. Vous pouvez demander à l'agent de stocker les connaissances en appelant la méthode add_knowledge
.
agent.clear_knowledge()
agent.add_knowledge("The user's birthday is February 10.")
agent.add_knowledge("Refer to the user as 'boss'.")
response = agent.reply("Today is February 10. I think this is an important date. Can you remind me?")
print(response)
LTMAgent
est un système RAG transparent. L'exemple ltm_agent_with_wiki montre comment ajouter des articles Wikipédia à la base de connaissances de l'agent.
Vous pouvez conserver la configuration de l'agent et ses mémoires/connaissances en obtenant son état sous forme de chaîne via la méthode state_as_text
.
state_text = agent.state_as_text()
# Persist state_text to secondary storage
Pour créer un agent à partir d'un texte d'état, appelez la méthode from_state_text
.
agent2 = LTMAgent.from_state_text(state_text)
Notez que cela ne restaure pas la session de conversation. Pour conserver la session de conversation, appelez la méthode state_as_text
de la session.
from goodai.ltm.agent import LTMAgentSession
session_state_text = agent.session.state_as_text()
# session_state_text can be persisted in secondary storage
# The session.session_id field can serve as an identifier of the persisted session
# Now let's restore the session in agent2
p_session = LTMAgentSession.from_state_text(session_state_text)
agent2.use_session(p_session)
L'extrait de code suivant crée une instance du LTM, charge du texte, puis récupère les passages de texte les plus pertinents (morceaux développés) en fonction d'une requête :
from goodai.ltm.mem.auto import AutoTextMemory
mem = AutoTextMemory.create()
mem.add_text("Lorem ipsum dolor sit amet, consectetur adipiscing elitn")
mem.add_text("Duis aute irure dolor in reprehenderit in voluptate velit esse cillum doloren",
metadata={'title': 'My document', 'tags': ['latin']})
r_memories = mem.retrieve(query='dolorem eum fugiat quo voluptas nulla pariatur?', k=3)
Une instance de mémoire par défaut peut être créée comme suit :
from goodai.ltm.mem.auto import AutoTextMemory
mem = AutoTextMemory.create()
Vous pouvez également configurer la mémoire en passant des paramètres à la méthode create
. Dans l'exemple suivant, la mémoire utilise un tokenizer « gpt2 » pour le segmentage, un modèle T5 pour les intégrations, un index FAISS pour l'intégration du stockage au lieu d'une simple base de données vectorielle et une configuration de segmentation personnalisée.
import torch
from transformers import AutoTokenizer
from goodai.ltm.embeddings.auto import AutoTextEmbeddingModel
from goodai.ltm.mem.auto import AutoTextMemory
from goodai.ltm.mem.config import TextMemoryConfig
from goodai.ltm.mem.mem_foundation import VectorDbType
embedding_model = AutoTextEmbeddingModel.from_pretrained('st:sentence-transformers/sentence-t5-base')
tokenizer = AutoTokenizer.from_pretrained('gpt2')
config = TextMemoryConfig()
config.chunk_capacity = 30 # tokens
config.queue_capacity = 10000 # chunks
mem = AutoTextMemory.create(emb_model=embedding_model,
matching_model=None,
tokenizer=tokenizer,
vector_db_type=VectorDbType.FAISS_FLAT_L2,
config=config,
device=torch.device('cuda:0'))
Appelez la méthode add_text
pour ajouter du texte à la mémoire. Le texte peut être constitué d'expressions, de phrases ou de documents.
mem.add_text("Lorem ipsum dolor sit amet, consectetur adipiscing elitn")
En interne, la mémoire décomposera et indexera automatiquement le texte.
Le texte peut être associé à un dictionnaire de métadonnées arbitraire, tel que :
mem.add_text("Duis aute irure dolor in reprehenderit in voluptate velit esse cillum doloren",
metadata={'title': 'My document', 'tags': ['latin']})
La mémoire concatène le texte stocké à l'aide add_text
avec tout texte précédemment envoyé à la mémoire, mais vous pouvez appeler add_separator
pour vous assurer qu'aucun nouveau texte n'est ajouté aux morceaux créés précédemment.
Pour récupérer une liste de passages associés à une requête, appelez la méthode retrieve
:
r_memories = mem.retrieve("What does Jake propose?", k=2)
La méthode retrieve
renvoie une liste d'objets de type RetrievedMemory
, par ordre décroissant de pertinence. Chaque mémoire récupérée possède les propriétés suivantes :
passage
: Le texte du souvenir. Cela correspond au texte trouvé dans un bloc correspondant, mais il peut être développé en utilisant le texte des blocs adjacents.timestamp
: L'heure (en secondes depuis Epoch par défaut) à laquelle le morceau récupéré a été créé.distance
: Distance calculée entre la requête et le passage du chunk.relevance
: Un nombre entre 0 et 1 représentant la pertinence de la mémoire récupérée.confidence
: si un modèle de correspondance requête-passage est disponible, il s'agit de la probabilité attribuée par le modèle.metadata
: métadonnées associées au texte récupéré, le cas échéant. Un modèle d'intégration est chargé comme suit :
from goodai.ltm.embeddings.auto import AutoTextEmbeddingModel
em = AutoTextEmbeddingModel.from_pretrained(model_name)
Le model_name
peut être l'un des éléments suivants :
"st:"
, par exemple, "st:sentence-transformers/multi-qa-mpnet-base-cos-v1"
."flag:"
, par exemple, "flag:BAAI/bge-base-en-v1.5"
."openai:"
, par exemple, "openai:text-embedding-ada-002"
.Nom | Modèle de base | # paramètres | # intégration de stockage |
---|---|---|---|
em-MiniLM-p1-01 | multi-qa-MiniLM-L6-cos-v1 | 22,7 m | 1 |
em-MiniLM-p3-01 | multi-qa-MiniLM-L6-cos-v1 | 22,7 m | 3 |
em-distilroberta-p1-01 | transformateurs de phrases/all-distrilroberta-v1 | 82,1 m | 1 |
em-distilroberta-p3-01 | transformateurs de phrases/all-distrilroberta-v1 | 82,1 m | 3 |
em-distilroberta-p5-01 | transformateurs de phrases/all-distrilroberta-v1 | 82,1 m | 5 |
Pour obtenir des intégrations pour une liste de requêtes, appelez la méthode encode_queries
, comme suit :
r_emb = em.encode_queries(['hello?'])
Cela renvoie un tableau numpy. Pour obtenir un tenseur Pytorch, ajoutez le paramètre convert_to_tensor
:
r_emb = em.encode_queries(['hello?'], convert_to_tensor=True)
Pour obtenir des incorporations pour une liste de passages, appelez la méthode encode_corpus
, comme suit :
s_emb = em.encode_corpus(['it was...', 'the best of...'])
Les requêtes et les passages peuvent avoir plusieurs intégrations. Les tenseurs d'intégration ont 3 axes : la taille du lot, le nombre d'intégrations et le nombre de dimensions d'intégration. En règle générale, le nombre d'intégrations par requête/passage sera de 1, à quelques exceptions près.
Un modèle de correspondance/reclassement de passages de requête peut être chargé comme suit :
from goodai.ltm.reranking.auto import AutoTextMatchingModel
model = AutoTextMatchingModel.from_pretrained(model_name)
Le model_name
peut être l'un des éléments suivants :
Par défaut, les instances de mémoire n'utilisent pas de modèle de correspondance de passage de requête. Pour en activer un, il doit être configuré comme suit :
from goodai.ltm.embeddings.auto import AutoTextEmbeddingModel
from goodai.ltm.mem.auto import AutoTextMemory
from goodai.ltm.mem.config import TextMemoryConfig
from goodai.ltm.reranking.auto import AutoTextMatchingModel
# Low-resource embedding model
emb_model = AutoTextEmbeddingModel.from_pretrained('em-MiniLM-p1-01')
# QPM model that boosts retrieval accuracy
qpm_model = AutoTextMatchingModel.from_pretrained('em:em-distilroberta-p5-01')
config = TextMemoryConfig()
config.reranking_k_factor = 8
mem = AutoTextMemory.create(matching_model=qpm_model, emb_model=emb_model, config=config)
Le paramètre reranking_k_factor
indique à la mémoire combien de candidats elle doit prendre en compte pour le reclassement. L'utilisateur demande k
mémoires. L'algorithme de reclassement considère les morceaux k * reranking_k_factor
.
La méthode predict
du modèle prend une liste de tuples de passages de requête et renvoie une liste de flottants représentant les probabilités de correspondance estimées. Exemple:
model = AutoTextMatchingModel.from_pretrained('em:em-distilroberta-p5-01')
sentences = [
('Mike: What is your favorite color?', 'Steve: My favorite color is purple.'),
('Name the inner planets.', 'It was the best of times, it was the worst of times.'),
]
prob = model.predict(sentences)
print(prob)
Voir les évaluations README.
Reportez-vous à la page du projet goodai-ltm-benchmark.
Un exemple de code supplémentaire peut être trouvé dans le dossier examples
.