Skip to content

Commit

Permalink
feat(document) make a better collections command
Browse files Browse the repository at this point in the history
  • Loading branch information
Ledoux committed Nov 7, 2024
1 parent 2f4d5c3 commit 364333a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 20 deletions.
2 changes: 1 addition & 1 deletion app/bot_msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AlbertMsg:
shorts = {
"help": f"Pour retrouver ce message informatif, tapez `{COMMAND_PREFIX}aide`. Pour les geek tapez `{COMMAND_PREFIX}aide -v`.",
"reset": f"Pour ré-initialiser notre conversation, tapez `{COMMAND_PREFIX}reset`",
"collections": f"Pour modifier l'ensemble des collections utilisées quand vous me posez une question, tapez `{COMMAND_PREFIX}collections list/use/unuse COLLECTION_NAME/all`",
"collections": f"Pour modifier l'ensemble des collections utilisées quand vous me posez une question, tapez `{COMMAND_PREFIX}collections list/use/unuse/info COLLECTION_NAME/{Config().albert_all_public_command}`",
"conversation": f"Pour activer/désactiver le mode conversation, tapez `{COMMAND_PREFIX}conversation`",
"debug": f"Pour afficher des informations sur la configuration actuelle, `{COMMAND_PREFIX}debug`",
"model": f"Pour modifier le modèle, tapez `{COMMAND_PREFIX}model MODEL_NAME`",
Expand Down
80 changes: 64 additions & 16 deletions app/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
flush_collections_with_name,
get_all_public_collections,
get_or_create_collection_with_name,
get_document_names,
get_or_not_collection_with_name,
get_documents,
generate,
get_available_models,
get_available_modes,
Expand Down Expand Up @@ -417,8 +418,8 @@ async def albert_collection(ep: EventParser, matrix_client: MatrixClient):
await matrix_client.room_typing(ep.room.room_id)
command = ep.get_command()
if len(command) <= 1:
message = f"La commande !collections nécessite de donner list/use/unuse puis <nom_de_collection>/{config.albert_all_public_command} :"
message += "\n\nExemple: `!collections use ma_collection`"
message = f"La commande !collections nécessite de donner list/use/unuse/info puis éventuellement <nom_de_collection>/{config.albert_all_public_command} :"
message += "\n\nExemple: `!collections use decisions-adlc`"
elif command[1] != 'list' and len(command) <= 2:
if command[1] not in ['use', 'unuse']:
message = f"La commande !collections {command[1]} n'est pas reconnue, seul list/use/unuse sont autorisés"
Expand All @@ -428,22 +429,68 @@ async def albert_collection(ep: EventParser, matrix_client: MatrixClient):
else:
method = command[1]
if method == 'list':
collection_names = ','.join([c['name'] if c['name'] != ep.room.room_id else 'ma_collection_privée' for c in config.albert_collections_by_id.values()])
if collection_names == '':
collections = config.albert_collections_by_id.values()
collection_display_names = [c['name'] if c['name'] != ep.room.room_id else config.albert_my_private_collection_name for c in collections]
collection_ids = [c['id'] for c in collections]
collection_infos = '\n - ' + '\n - '.join([f"{display_name}" for display_name, collection_id in zip(collection_display_names, collection_ids)])
if not collections:
message = "Vous n'avez pas de collections enregistrées pour le moment qui pourraient m'aider à répondre à vos questions."
else:
message = f"Les collections {collection_names} sont disponibles pour vos questions."
message = (
"Les collections :\n"
f"{collection_infos}\n\n"
"sont prises en compte pour m'aider à répondre à vos questions."
)
collections = get_all_public_collections(config)
message += "\n\nNotez que les collections publiques à votre disposition sont:\n"
message += '\n - ' + '\n - '.join([f"{c['name']}" for c in collections])
message += f"\n\nVous pouvez toutes les ajouter d'un coup en utilisant la commande `!collections use {config.albert_all_public_command}`"
elif method == 'info':
collection_name = command[2] if command[2] != config.albert_my_private_collection_name else ep.room.room_id
collection = get_or_not_collection_with_name(config, collection_name)
if not collection:
message = f"La collection {collection_name} n'existe pas."
else:
document_infos = [f"{d['name']} ({d['id']})" for d in get_documents(config, collection['id'])]
if not document_infos:
message = (
f"Collection '{command[2]}' ({collection['id']}) : \n\n"
f"Aucun document n'est présent dans cette collection ({collection['id']})."
)
else:
document_infos_message = '\n - ' + '\n - '.join(document_infos)
message = (
f"Collection '{command[2]}' ({collection['id']}) : \n\n"
"Voici les documents actuellement présents dans la collection : \n\n"
f"{document_infos_message}"
"\n\n"
)
elif method == 'use':
collections = get_all_public_collections(config) if (command[2] == config.albert_all_public_command) else \
[get_or_create_collection_with_name(config, command[2])]
collection_names = ','.join([c['name'] for c in collections])
for collection in collections:
config.albert_collections_by_id[collection["id"]] = collection
message = f"Les collections {collection_names} sont ajoutées à vos collections."
if command[2] == config.albert_all_public_command:
collections = get_all_public_collections(config)
else:
collection = get_or_not_collection_with_name(config, command[2])
if not collection:
message = f"La collection {command[2]} n'existe pas."
collections = []
else:
collections = [collection]
if collections:
collection_names = ','.join([c['name'] for c in collections])
for collection in collections:
config.albert_collections_by_id[collection["id"]] = collection
collection_infos = '\n - ' + '\n - '.join([f"{c['name']}" for c in config.albert_collections_by_id.values()])
message = (
f"Les collections {collection_names} sont ajoutées à vos collections.\n\n" if len(collections) > 1 else f"La collection {command[2]} est ajoutée à vos collections.\n\n"
"Maintenant, les collections :\n"
f"{collection_infos}\n\n"
"sont disponibles pour m'aider à répondre à vos questions."
)
else:
collection_names = ','.join([c['name'] for c in config.albert_collections_by_id.values()])
collections = config.albert_collections_by_id.values()
collection_names = ','.join([c['name'] for c in collections])
config.albert_collections_by_id = {}
if collection_names == '':
if not collections:
message = "Il n'y avait pas de collections à retirer."
else:
message = f"Les collections {collection_names} sont retirées de vos collections."
Expand All @@ -467,13 +514,14 @@ async def albert_document(ep: EventParser, matrix_client: MatrixClient):
config.albert_collections_by_id[collection['id']] = collection
file = await get_decrypted_file(ep)
upload_file(config, file, collection['id'])
private_documents_names = get_document_names(config, collection['id'])
private_document_infos = [d['name'] for d in get_documents(config, collection['id'])]
private_document_infos_message = '\n - ' + '\n - '.join(private_document_infos)
response = (
"Votre document : \n\n"
f"\"{file.name}\"\n\n"
"a été chargé dans votre collection privée.\n\n"
"Voici les documents actuellement présents dans votre collection privée : \n\n"
f"{private_documents_names}"
f"{private_document_infos_message}"
"\n\n"
"Je tiendrai compte de tous ces documents pour répondre. \n\n"
"Vous pouvez taper \"!mode norag\" pour vider votre collection privée de tous ces documents."
Expand Down
1 change: 1 addition & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Config(BaseConfig):
albert_with_history: bool = Field(True, description="Conversational mode")
albert_history_lookup: int = Field(0, description="How far we lookup in the history")
albert_max_rewind: int = Field(20, description="Max history rewind for stability purposes")
albert_my_private_collection_name: str = Field("ma_collection_privée", description="Name of the private collection for the user")
albert_all_public_command: str = Field("<all_public>", description="Command to use to get all public collections")
conversation_obsolescence: int = Field(
15 * 60, description="time after which a conversation is considered obsolete, in seconds"
Expand Down
16 changes: 13 additions & 3 deletions app/core_llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ def get_all_public_collections(config: Config) -> dict:
]


def get_or_not_collection_with_name(config: Config, collection_name: str) -> dict | None:
api_key = config.albert_api_token
url = os.path.join(config.albert_api_url, API_PREFIX_V1)
aclient = AlbertApiClient(base_url=url, api_key=api_key)
collections = aclient.fetch_collections().values()
for collection in collections:
if collection['name'] == collection_name:
return collection
return None


def get_or_create_collection_with_name(config: Config, collection_name: str) -> dict:
api_key = config.albert_api_token
url = os.path.join(config.albert_api_url, API_PREFIX_V1)
Expand Down Expand Up @@ -136,12 +147,11 @@ def upload_file(config: Config, file: BytesIO, collection_id: str) -> dict:
return aclient.upload_file(file, collection_id)


def get_document_names(config: Config, collection_id: str) -> list[str]:
def get_documents(config: Config, collection_id: str) -> list[dict]:
api_key = config.albert_api_token
url = os.path.join(config.albert_api_url, API_PREFIX_V1)
aclient = AlbertApiClient(base_url=url, api_key=api_key)
documents = aclient.fetch_documents(collection_id)
return "\n".join([f"- {document['name']}" for document in documents])
return aclient.fetch_documents(collection_id)


class AlbertApiClient:
Expand Down

0 comments on commit 364333a

Please sign in to comment.