Guide

Confluence : Base de connaissances IA pour equipes

25 mars 2026
Equipe Ailog

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

MetriqueMoyenne entreprise
Temps passe a chercher20% du temps de travail
Pages jamais consultees60% apres 6 mois
Questions repetees au support40% sont dans la doc
Satisfaction recherche Confluence3.2/10

Recherche native vs RAG

CritereRecherche ConfluenceRecherche RAG
Type de requeteMots-cles exactsLangage naturel
ResultatListe de pagesReponse directe
Multi-pagesNonSynthetise plusieurs sources
ContexteAucunHistorique conversationnel
FormatsTexte uniquementTexte + tableaux + code
PertinenceRecence > pertinencePertinence 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

  1. Extraction : Le connecteur interroge l'API Confluence v2 pour recuperer les pages
  2. Parsing : Le HTML Confluence est converti en Markdown propre
  3. Chunking : Les documents sont decoupes en segments de 512 tokens
  4. Embedding : Chaque chunk est vectorise avec BGE-M3 (multilingue)
  5. Indexation : Les vecteurs sont stockes dans Qdrant avec metadonnees
  6. Retrieval : Les questions sont matchees semantiquement aux chunks
  7. Reranking : Un second modele affine le classement
  8. Generation : Le LLM synthetise la reponse avec citations

Connecteur Confluence complet

Voici l'implementation de reference pour extraire le contenu Confluence :

DEVELOPERpython
from 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) :

DEVELOPERpython
from 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

DEVELOPERpython
CONFLUENCE_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 :

  1. Telecharge le client Cisco AnyConnect depuis [lien interne]
  2. Serveur : vpn.company.com
  3. Utilise tes identifiants Active Directory
  4. 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 :

  1. Identifie la formation avec ton manager
  2. Remplis le formulaire F-RH-015 sur Confluence
  3. Fait valider par ton N+1 puis par RH
  4. 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/health

Acces staging : demander au DevOps (#devops sur Slack).

Source: [Tech > DevOps > Deploiement] (decembre 2025)

Bonnes pratiques

Structurer Confluence pour le RAG

PratiqueBenefice
Hierarchie claire (3 niveaux max)Chunking optimal
Titres descriptifsMeilleure recherche
Labels standardisesFiltrage facile
Templates de pagesCoherence du format
Pages courtes et focaliseesPrecision des reponses

Gerer les permissions

Le RAG respecte les permissions Confluence :

  1. Creer un compte service dedie avec acces lecture
  2. Limiter aux espaces publics/internes selon le cas d'usage
  3. 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

FAQ

La recherche Confluence fonctionne par mots-cles exacts et retourne une liste de pages. Le RAG comprend le sens de la question, synthetise l'information de plusieurs pages et donne une reponse directe avec sources. "Comment configurer le VPN" trouve des resultats meme si les pages utilisent "acces distant".
Le RAG peut filtrer par date de mise a jour et prioriser les pages recentes. Le prompt systeme peut instruire le chatbot de signaler quand une information date de plus d'un an. Une synchronisation complete periodique permet aussi de supprimer les pages archivees de l'index.
Pour une utilisation d'equipe, un compte de service (API token) est recommande. Il donne acces a tous les espaces partages avec ce compte. Les tokens utilisateur donnent acces aux memes espaces que l'utilisateur, ce qui peut poser des problemes si quelqu'un quitte l'entreprise.
Les commentaires de pages peuvent etre indexes si souhaite (utile pour les discussions importantes). Les pieces jointes (PDF, Word) necessitent un parsing supplementaire mais sont supportees. Les images et diagrammes ne sont pas indexes en texte, sauf leur legende.
Le RAG herite des permissions du compte utilise pour l'extraction. En creant un compte service avec acces aux seuls espaces publics/internes, vous garantissez que les espaces confidentiels ne sont jamais indexes. Pour un controle plus fin, des filtres par espace sont possibles. ---

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

ragconfluenceatlassianknowledge basedocumentationchatbot interne

Articles connexes

Ailog Assistant

Ici pour vous aider

Salut ! Pose-moi des questions sur Ailog et comment intégrer votre RAG dans vos projets !