File size: 3,009 Bytes
da21448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from collections.abc import Sequence

from techdocs_graphrag.models import EntityType, GraphFact, RetrievalContext, RetrievedChunk

ENTITY_TYPES = ", ".join(entity_type.value for entity_type in EntityType)

EXTRACTION_SYSTEM_PROMPT = f"""\
Tu es un système d'extraction de graphe de connaissances pour de la documentation technique.

À partir du texte fourni par l'utilisateur, extrais :
1. les entités techniques importantes (composants, classes, fonctions, bibliothèques, concepts...) ;
2. le type de chaque entité, choisi parmi : {ENTITY_TYPES} ;
3. les relations factuelles explicitement affirmées par le texte ;
4. une preuve textuelle courte (25 mots maximum) recopiée du texte pour chaque relation.

Règles :
- Nomme chaque entité sous sa forme canonique, telle qu'écrite dans le code (ex. StateGraph, MemorySaver).
- Utilise le singulier pour les concepts (Channel et non Channels).
- Écris les relations en anglais, en UPPER_SNAKE_CASE, orientées source -> cible
  (ex. USES, PERSISTS_WITH, PART_OF, DEPENDS_ON, CONFIGURES, RETURNS, RAISES, EXTENDS, ENABLES).
- N'invente aucune relation absente du texte.
- Si le texte ne contient rien d'exploitable, renvoie des listes vides.

Réponds uniquement avec un objet JSON valide de cette forme :
{{
  "entities": [{{"name": "StateGraph", "type": "Component"}}],
  "relations": [
    {{
      "source": "StateGraph",
      "relation": "USES",
      "target": "Channel",
      "evidence": "StateGraph utilise des Channels pour gérer l'état"
    }}
  ]
}}
"""

ANSWER_SYSTEM_PROMPT = """\
Tu es un assistant expert en documentation technique.

Règles :
- Réponds uniquement à partir du contexte fourni : faits du graphe et extraits documentaires.
- Réponds dans la langue de la question.
- Explique clairement comment les composants sont reliés entre eux lorsque c'est utile.
- Cite tes sources en ligne sous la forme [nom_du_document].
- Ajoute un court exemple de code uniquement s'il est présent ou directement déductible du contexte.
- Si le contexte ne suffit pas, dis-le explicitement au lieu d'inventer.
"""

NO_FACTS = "Aucun fait pertinent."
NO_CHUNKS = "Aucun extrait pertinent."


def render_answer_prompt(question: str, context: RetrievalContext) -> str:
    return "\n\n".join(
        (
            f"Question :\n{question}",
            f"Faits du graphe de connaissances :\n{render_facts(context.facts)}",
            f"Extraits documentaires :\n{render_chunks(context.chunks)}",
        )
    )


def render_facts(facts: Sequence[GraphFact]) -> str:
    if not facts:
        return NO_FACTS
    return "\n".join(
        f"- {fact.source} --{fact.relation}--> {fact.target}"
        f" | preuve : {' / '.join(fact.evidence[:2]) or 'n/a'}"
        f" | sources : {', '.join(fact.documents) or 'n/a'}"
        for fact in facts
    )


def render_chunks(chunks: Sequence[RetrievedChunk]) -> str:
    if not chunks:
        return NO_CHUNKS
    return "\n\n".join(f"[{chunk.document}]\n{chunk.text}" for chunk in chunks)