Confluence : Base de connaissances IA pour equipes
Guide complet pour deployer un assistant RAG sur Confluence. Transformez votre documentation Atlassian en base de connaissances interrogeable par IA.
Confluence : Base de connaissances IA pour equipes
Confluence est le pilier de la documentation d'entreprise dans l'ecosysteme Atlassian. Des millions d'equipes l'utilisent pour centraliser processus, guides techniques, et decisions strategiques. Mais avec le temps, meme les wikis les mieux organises deviennent des labyrinthes ou l'information se perd. Les employes passent en moyenne 20% de leur temps a chercher des informations qu'ils savent exister quelque part.
Un assistant RAG transforme cette masse documentaire en interface conversationnelle. Au lieu de naviguer dans des arborescences complexes, vos equipes posent leurs questions en langage naturel et obtiennent des reponses synthetisees avec sources. Ce guide detaille l'integration Confluence + RAG de A a Z.
Le probleme Confluence a grande echelle
Symptomes courants
Apres quelques annees d'utilisation, Confluence presente des defis recurrents :
- "Je sais que ca existe quelque part" : L'information est la, mais introuvable
- Navigation labyrinthique : Trop d'espaces, de sous-pages, de hierarchies
- Contenu obsolete : Pages non maintenues qui polluent les resultats
- Duplication : Memes informations dans plusieurs espaces
- Onboarding difficile : Les nouveaux arrivent perdus dans la documentation
Chiffres revelateurs
| Metrique | Moyenne entreprise |
|---|---|
| Temps passe a chercher | 20% du temps de travail |
| Pages jamais consultees | 60% apres 6 mois |
| Questions repetees au support | 40% sont dans la doc |
| Satisfaction recherche Confluence | 3.2/10 |
Recherche native vs RAG
| Critere | Recherche Confluence | Recherche RAG |
|---|---|---|
| Type de requete | Mots-cles exacts | Langage naturel |
| Resultat | Liste de pages | Reponse directe |
| Multi-pages | Non | Synthetise plusieurs sources |
| Contexte | Aucun | Historique conversationnel |
| Formats | Texte uniquement | Texte + tableaux + code |
| Pertinence | Recence > pertinence | Pertinence semantique |
Architecture Confluence + RAG
L'integration repose sur trois piliers : extraction via l'API Confluence, indexation vectorielle, et interface conversationnelle.
┌─────────────────────────────────────────────────────────────────────────┐
│ Architecture Confluence + RAG │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ CONFLUENCE PROCESSING VECTOR DB │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Espaces │────────────▶│ Parsing │─────────▶│ Qdrant │ │
│ │ │ │ HTML→MD │ │ │ │
│ │ - IT │ └──────┬───────┘ │ HNSW │ │
│ │ - RH │ │ │ Index │ │
│ │ - Produit │ ┌──────┴───────┐ └─────┬─────┘ │
│ │ - Tech │ │ Chunking │ │ │
│ └──────┬───────┘ │ 512 tokens │ │ │
│ │ └──────┬───────┘ │ │
│ ┌──────┴───────┐ │ │ │
│ │ REST API │ ┌──────┴───────┐ │ │
│ │ v2 │ │ Embeddings │ │ │
│ └──────────────┘ │ BGE-M3 │ │ │
│ └──────────────┘ │ │
│ │ │
│ QUERY PIPELINE │ │
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │ │
│ │ Question │────▶│ Retrieval │◀────│ Reranker │◀──┘ │
│ │ employe │ │ Top-30 │ │ Top-5 │ │
│ └──────────────┘ └─────────────┘ └──────┬───────┘ │
│ │ │
│ ┌──────────────┐ ┌──────┴───────┐ │
│ │ Reponse │◀───│ LLM │ │
│ │ + Sources │ │ GPT-4/Claude│ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Flux de donnees
- Extraction : Le connecteur interroge l'API Confluence v2 pour recuperer les pages
- Parsing : Le HTML Confluence est converti en Markdown propre
- Chunking : Les documents sont decoupes en segments de 512 tokens
- Embedding : Chaque chunk est vectorise avec BGE-M3 (multilingue)
- Indexation : Les vecteurs sont stockes dans Qdrant avec metadonnees
- Retrieval : Les questions sont matchees semantiquement aux chunks
- Reranking : Un second modele affine le classement
- Generation : Le LLM synthetise la reponse avec citations
Connecteur Confluence complet
Voici l'implementation de reference pour extraire le contenu Confluence :
DEVELOPERpythonfrom atlassian import Confluence from bs4 import BeautifulSoup import hashlib from typing import Optional import re class ConfluenceConnector: def __init__(self, url: str, username: str, api_token: str): """ Initialise le connecteur Confluence. Args: url: URL de l'instance (ex: https://company.atlassian.net) username: Email de l'utilisateur api_token: Token API Atlassian """ self.confluence = Confluence( url=url, username=username, password=api_token, cloud=True ) self.base_url = url def get_all_spaces(self) -> list: """Recupere tous les espaces accessibles.""" spaces = [] start = 0 limit = 50 while True: result = self.confluence.get_all_spaces( start=start, limit=limit, expand='description.plain' ) for space in result.get('results', []): spaces.append({ 'key': space['key'], 'name': space['name'], 'type': space.get('type', 'global'), 'description': space.get('description', {}).get('plain', {}).get('value', '') }) if len(result.get('results', [])) < limit: break start += limit return spaces def get_space_pages(self, space_key: str, include_archived: bool = False) -> list: """ Recupere toutes les pages d'un espace. Args: space_key: Cle de l'espace (ex: 'IT', 'RH') include_archived: Inclure les pages archivees Returns: Liste de documents formates pour le RAG """ pages = [] start = 0 limit = 50 while True: try: result = self.confluence.get_all_pages_from_space( space_key, start=start, limit=limit, expand='body.storage,ancestors,version,metadata.labels' ) except Exception as e: print(f"Erreur espace {space_key}: {e}") break for page in result: # Filtrer les pages archivees si demande if not include_archived and page.get('status') == 'archived': continue doc = self._format_page(page, space_key) if doc and len(doc['content']) > 100: # Ignorer pages trop courtes pages.append(doc) if len(result) < limit: break start += limit return pages def _format_page(self, page: dict, space_key: str) -> dict: """Formate une page Confluence en document RAG.""" # Extraire et nettoyer le contenu HTML html_content = page.get('body', {}).get('storage', {}).get('value', '') text_content = self._html_to_markdown(html_content) # Construire le chemin hierarchique (breadcrumb) ancestors = page.get('ancestors', []) path_parts = [a['title'] for a in ancestors] + [page['title']] breadcrumb = ' > '.join(path_parts) # Extraire les labels labels = [ label['name'] for label in page.get('metadata', {}).get('labels', {}).get('results', []) ] # Hash pour detecter les changements content_hash = hashlib.md5(text_content.encode()).hexdigest() # Version et date version = page.get('version', {}) return { "id": f"confluence_{page['id']}", "title": page['title'], "content": f"# {page['title']}\n\n**Chemin**: {breadcrumb}\n\n{text_content}", "metadata": { "source": "confluence", "source_type": "documentation", "space_key": space_key, "page_id": page['id'], "url": f"{self.base_url}/wiki/spaces/{space_key}/pages/{page['id']}", "breadcrumb": breadcrumb, "labels": labels, "version": version.get('number', 1), "last_updated": version.get('when'), "last_updated_by": version.get('by', {}).get('displayName'), "content_hash": content_hash } } def _html_to_markdown(self, html: str) -> str: """ Convertit le HTML Confluence en Markdown propre. Gere les specificites du format Confluence : - Macros (code, panel, note, warning) - Tableaux - Listes imbriquees - Liens et mentions """ if not html: return "" soup = BeautifulSoup(html, 'html.parser') # Traiter les macros code for code_block in soup.find_all('ac:structured-macro', {'ac:name': 'code'}): language = code_block.get('ac:language', '') code_body = code_block.find('ac:plain-text-body') if code_body: code_text = code_body.get_text() code_block.replace_with(f"\n```{language}\n{code_text}\n```\n") # Traiter les panels et notes for panel in soup.find_all('ac:structured-macro', {'ac:name': ['panel', 'note', 'warning', 'info']}): panel_type = panel.get('ac:name', 'note') body = panel.find('ac:rich-text-body') if body: panel_text = body.get_text(separator='\n') panel.replace_with(f"\n> **{panel_type.upper()}**: {panel_text}\n") # Traiter les tableaux for table in soup.find_all('table'): rows = table.find_all('tr') if rows: md_table = self._table_to_markdown(rows) table.replace_with(md_table) # Traiter les headers for i in range(1, 7): for header in soup.find_all(f'h{i}'): header.replace_with(f"\n{'#' * i} {header.get_text()}\n") # Traiter les listes for ul in soup.find_all('ul'): items = ul.find_all('li', recursive=False) list_text = '\n'.join([f"- {li.get_text()}" for li in items]) ul.replace_with(f"\n{list_text}\n") for ol in soup.find_all('ol'): items = ol.find_all('li', recursive=False) list_text = '\n'.join([f"{i+1}. {li.get_text()}" for i, li in enumerate(items)]) ol.replace_with(f"\n{list_text}\n") # Nettoyer le texte final text = soup.get_text(separator='\n') text = re.sub(r'\n{3,}', '\n\n', text) # Max 2 lignes vides text = re.sub(r' +', ' ', text) # Espaces multiples return text.strip() def _table_to_markdown(self, rows) -> str: """Convertit un tableau HTML en Markdown.""" md_lines = [] for i, row in enumerate(rows): cells = row.find_all(['th', 'td']) cell_texts = [cell.get_text().strip().replace('|', '\\|') for cell in cells] md_lines.append('| ' + ' | '.join(cell_texts) + ' |') # Ajouter la ligne de separation apres le header if i == 0: md_lines.append('| ' + ' | '.join(['---'] * len(cells)) + ' |') return '\n' + '\n'.join(md_lines) + '\n' def get_page_comments(self, page_id: str) -> list: """Recupere les commentaires d'une page (optionnel).""" try: comments = self.confluence.get_page_comments( page_id, expand='body.storage', depth='all' ) return [ { 'author': c.get('author', {}).get('displayName', 'Unknown'), 'content': BeautifulSoup( c.get('body', {}).get('storage', {}).get('value', ''), 'html.parser' ).get_text(), 'date': c.get('created') } for c in comments.get('results', []) ] except: return [] class ConfluenceMultiSpaceConnector(ConfluenceConnector): """Extension pour gerer plusieurs espaces avec filtrage.""" def get_all_documents( self, space_keys: list = None, exclude_spaces: list = None, labels_filter: list = None ) -> list: """ Recupere les documents de plusieurs espaces. Args: space_keys: Liste des espaces a inclure (None = tous) exclude_spaces: Espaces a exclure labels_filter: Ne garder que les pages avec ces labels Returns: Liste de tous les documents """ all_docs = [] # Recuperer la liste des espaces spaces = self.get_all_spaces() for space in spaces: key = space['key'] # Filtrer les espaces if space_keys and key not in space_keys: continue if exclude_spaces and key in exclude_spaces: continue print(f"Indexation espace: {space['name']} ({key})") pages = self.get_space_pages(key) # Filtrer par labels si demande if labels_filter: pages = [ p for p in pages if any(label in p['metadata']['labels'] for label in labels_filter) ] all_docs.extend(pages) return all_docs
Synchronisation et mise a jour
La synchronisation peut etre incrementale (efficace) ou complete (nettoyage) :
DEVELOPERpythonfrom datetime import datetime, timedelta import schedule class ConfluenceSyncManager: def __init__(self, connector: ConfluenceConnector, indexer): self.connector = connector self.indexer = indexer self.last_sync = None self.sync_history = [] def sync_incremental(self, spaces: list = None): """ Synchronisation incrementale. Ne traite que les pages modifiees depuis la derniere sync. """ if spaces is None: spaces = [s['key'] for s in self.connector.get_all_spaces()] updated_count = 0 for space_key in spaces: pages = self.connector.get_space_pages(space_key) for page in pages: last_updated = page['metadata'].get('last_updated') if last_updated: updated_dt = datetime.fromisoformat( last_updated.replace('Z', '+00:00') ) if self.last_sync is None or updated_dt > self.last_sync: self.indexer.upsert_document(page) updated_count += 1 self.last_sync = datetime.now() self.sync_history.append({ 'timestamp': self.last_sync, 'type': 'incremental', 'documents_updated': updated_count }) print(f"Sync incrementale: {updated_count} documents mis a jour") def sync_full(self, spaces: list = None): """Synchronisation complete avec remplacement.""" docs = self.connector.get_all_documents() if spaces is None else [] if spaces: for space_key in spaces: docs.extend(self.connector.get_space_pages(space_key)) self.indexer.replace_all(docs) self.last_sync = datetime.now() self.sync_history.append({ 'timestamp': self.last_sync, 'type': 'full', 'documents_indexed': len(docs) }) print(f"Sync complete: {len(docs)} documents indexes") def cleanup_deleted(self): """Supprime les documents dont les pages n'existent plus.""" indexed_ids = self.indexer.get_all_ids() current_pages = set() for space in self.connector.get_all_spaces(): pages = self.connector.get_space_pages(space['key']) for page in pages: current_pages.add(page['id']) # Trouver les IDs a supprimer to_delete = indexed_ids - current_pages if to_delete: self.indexer.delete_documents(list(to_delete)) print(f"Supprime {len(to_delete)} documents obsoletes") def start_confluence_sync_worker(sync_manager: ConfluenceSyncManager): """Demarre le worker de synchronisation.""" # Sync incrementale toutes les 15 minutes schedule.every(15).minutes.do(sync_manager.sync_incremental) # Sync complete hebdomadaire schedule.every().sunday.at("02:00").do(sync_manager.sync_full) # Nettoyage mensuel schedule.every(30).days.do(sync_manager.cleanup_deleted) while True: schedule.run_pending() time.sleep(60)
Prompt systeme optimise Confluence
DEVELOPERpythonCONFLUENCE_SYSTEM_PROMPT = """Tu es l'assistant documentation de {company_name}. Tu aides les employes a trouver des informations dans notre Confluence. ## Mission - Repondre en te basant UNIQUEMENT sur la documentation Confluence - Citer systematiquement l'espace et la page source - Indiquer la date de derniere mise a jour si pertinent - Orienter vers le bon contact si la question depasse la doc ## Regles 1. Ne jamais inventer d'information absente de la documentation 2. Privilegier les pages recemment mises a jour 3. Signaler si une information semble obsolete (> 1 an) 4. Adapter le niveau de detail a la question ## Format - Reponse directe d'abord - Details si necessaire - Source: [Espace > Page] (date) ## Documentation disponible {context} """
Cas d'usage concrets
1. Support IT interne
Question : "Comment configurer le VPN pour le teletravail ?"
Reponse RAG :
Pour configurer le VPN :
- Telecharge le client Cisco AnyConnect depuis [lien interne]
- Serveur : vpn.company.com
- Utilise tes identifiants Active Directory
- Pour le 2FA, utilise l'app Duo
En cas de probleme, ouvre un ticket IT via ServiceNow.
Source: [IT > Guide VPN Teletravail] (mis a jour il y a 2 mois)
2. Processus RH
Question : "Quelle est la procedure pour une demande de formation ?"
Reponse RAG :
Procedure de demande de formation :
- Identifie la formation avec ton manager
- Remplis le formulaire F-RH-015 sur Confluence
- Fait valider par ton N+1 puis par RH
- Budget: max 2000 EUR/an/employe
Delai de traitement : 2-3 semaines.
Source: [RH > Formation > Procedure demande] (janvier 2025)
3. Documentation technique
Question : "Comment deployer sur l'environnement de staging ?"
Reponse RAG :
Deploiement staging :
DEVELOPERbash# 1. Merger sur develop git checkout develop && git pull && git merge feature/xxx # 2. Lancer le pipeline ./scripts/deploy.sh staging # 3. Verifier curl https://staging.company.com/healthAcces staging : demander au DevOps (#devops sur Slack).
Source: [Tech > DevOps > Deploiement] (decembre 2025)
Bonnes pratiques
Structurer Confluence pour le RAG
| Pratique | Benefice |
|---|---|
| Hierarchie claire (3 niveaux max) | Chunking optimal |
| Titres descriptifs | Meilleure recherche |
| Labels standardises | Filtrage facile |
| Templates de pages | Coherence du format |
| Pages courtes et focalisees | Precision des reponses |
Gerer les permissions
Le RAG respecte les permissions Confluence :
- Creer un compte service dedie avec acces lecture
- Limiter aux espaces publics/internes selon le cas d'usage
- Ne jamais indexer les espaces confidentiels sans validation
Indicateurs de qualite
- Taux de reponses avec source
- Questions sans match (a ajouter a la doc)
- Pages les plus citees
- Feedback utilisateur
Ressources complementaires
- Base de connaissances entreprise - Guide pilier
- Notion + RAG - Alternative Notion
- SharePoint + RAG - Pour Microsoft 365
- Slack Bot RAG - Recherche dans les conversations
- Introduction au RAG - Les fondamentaux
FAQ
Connectez Confluence avec Ailog
Transformez votre documentation Confluence en assistant intelligent. Ailog simplifie l'integration :
- Connecteur Atlassian natif : Synchronisation automatique multi-espaces
- Recherche semantique : Trouvez l'info en langage naturel
- Respect des permissions : Acces granulaire par espace
- Historique des versions : Tracabilite complete
- Hebergement France : Conformite RGPD native
Testez Ailog gratuitement et deployez votre assistant Confluence en 15 minutes.
Tags
Articles connexes
Notion + RAG : Connecter votre wiki d'entreprise
Guide complet pour integrer Notion comme source de connaissances pour un chatbot RAG. Synchronisation, indexation, recherche semantique et cas d'usage pratiques.
Slack Bot RAG : Recherche intelligente dans vos conversations
Guide complet pour deployer un bot Slack RAG. Transformez l'historique de vos canaux en base de connaissances interrogeable par IA.
SharePoint + RAG : Exploiter vos documents Microsoft 365
Guide complet pour connecter SharePoint a un systeme RAG. Rendez vos documents Microsoft 365 interrogeables par IA avec recherche semantique.