langchain, proposé par Lance Martin. Ce framework permet de combiner plusieurs appels à un LLM dans une chaîne d’appel, pour obtenir des résultats plus pertinents.
Le framework langchain propose une intégration simple avec Google Drive. Chez OCTO, utilisant essentiellement Google Drive pour nos données internes, nous avons besoin d’une évolution majeure de cette intégration.
Pourquoi nous ne sommes pas satisfaits de l’implémentation proposée ?
Nous avons alors décidé de proposer une version plus évoluée. Cette dernière expose un Loader, un Retriever et un Tools, permettant au LLM d’interroger GDrive s’il le juge nécessaire.
Elle est complètement compatible avec l’API de Google Drive:
Par défaut, voici les différents types mime que nous traitons :
Voici quelques exemples d’utilisations:
from langchain_googledrive.document_loaders import GoogleDriveLoader
loader = GoogleDriveLoader(
gdrive_api_file=os.environ["GOOGLE_ACCOUNT_FILE"],
num_results=2,
template="gdrive-query",
query='machine learning',
supportsAllDrives=False,
)
for doc in loader.load():
print("---")
print(doc.page_content.strip()[:60]+"...")
Utilisation via un retriever, avec un template de recherche sur mesure.
from langchain import PromptTemplate
from langchain_googledrive.retrievers import GoogleDriveRetriever
retriever = GoogleDriveRetriever(
template=PromptTemplate(input_variables=['query'],
template="(fullText contains '{query}') "
"And mimeType='application/vnd.google-apps.document' "
"and modifiedTime > '2000-01-01T00:00:00' "
"and trashed=false"),
num_results=2,
includeItemsFromAllDrives=False,
supportsAllDrives=False,
)
for doc in retriever.get_relevant_documents("machine learning"):
print(f"{doc.metadata['name']}:")
print("---")
print(doc.page_content.strip()[:60]+"...")
Utilisation en tant que tools
from langchain_googledrive.utilities.google_drive import GoogleDriveAPIWrapper
from langchain_googledrive.tools.google_drive.tool import GoogleDriveSearchTool
folder_id='root'
# By default, search only in the filename.
tool = GoogleDriveSearchTool(
api_wrapper=GoogleDriveAPIWrapper(
folder_id=folder_id,
num_results=2,
template="gdrive-query-in-folder", # Search in the body of documents
)
)<br>
from langchain import OpenAI
from langchain.agents import initialize_agent, AgentType
llm = OpenAI(temperature=0)
agent = initialize_agent(
tools=[tool],
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
)
agent.run(
"Search in google drive, who is 'Yann LeCun' ?"
)
Tous les paramètres sont compatibles avec l’API list() de Google et peuvent être valorisés.
Comme vous pouvez le constater dans les exemples, il est possible d’utiliser un template de recherche. Pour spécifier de nouveaux patterns lors de la recherche, vous devez utiliser un PromptTemplate(). Les variables du prompt peuvent être valorisés via des paramètres supplémentaires type kwargs, dans le constructeur, ou lors de l’interrogation.
Il existe une liste de templates pré-paramétré qu’il suffit d’indiquer par leurs noms. Certains nécessitent des paramètres complémentaires ({query}, {folder_id} et/ou {mime_type}).
template | description |
---|---|
gdrive-all-in-folder | Retourne tous les documents compatibles depuis un folder_id |
gdrive-query | Fait une recherche GDrive sur le contenu des documents (query) |
gdrive-by-name | Fait une recherche sur les noms des fichiers (query) |
gdrive-query-in-folder | Fait une recherche de document, dans un répertoire et éventuellement ses sous-répertoires (si recursive=true) |
gdrive-mime-type | Recherche un mime_type spécifique |
gdrive-mime-type-in-folder | Recherche un mime_type spécifique dans un folder_id |
gdrive-query-with-mime-type | Faire une recherche (query) en filtrant sur un mime_type |
gdrive-query-with-mime-type-and-folder | Fait une recherche (query) avec un mime_type dans un folder_id |
loader = GoogleDriveLoader(
folder_id=folder_id,
recursive=False,
template="gdrive-query", # Default template to use
query="machine learning",
num_results=2, # Maximum number of file to load
supportsAllDrives=False, # GDrive `list()` parameter
)
for doc in loader.load():
print("---")
print(doc.page_content.strip()[:60]+"...")
Mais vous être libre d’enrichir tout cela. Par exemple, pour faire une recherche combinée: nom de fichier et contenu.
from langchain.prompts.prompt import PromptTemplate
loader = GoogleDriveLoader(
folder_id=folder_id,
recursive=False,
template=PromptTemplate(
input_variables=["query", "query_name"],
template="fullText contains '{query}' and name contains '{query_name}' and trashed=false",
),
query="machine learning",
query_name="ML",
num_results=2, # Maximum number of file to load
)
for doc in loader.load():
print("---")
print(doc.page_content.strip()[:60]+"...")
Le paramètre mode accepte différentes valeurs:
loader = GoogleDriveLoader(
template="gdrive-mime-type",
mime_type="application/vnd.google-apps.presentation",
gslide_mode="slide",
num_results=2, # Maximum number of file to load
)
for doc in loader.load():
print("---")
print(doc.page_content.strip()[:60]+"...")
Le paramètre gsheet_mode accepte également différentes valeurs:
Nous avons bien essayé de proposer un pull-request, mais le code est trop important pour trouver une âme courageuse pour le relire (+2000 lignes).
Finalement, nous avons opté pour un composant autonome, dont la doc de langchain fait mention.
Nous espérons que cette contribution vous sera utile. Au vu des statistiques de download, cela semble le cas.