graphsight-langgraph 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. graphsight_langgraph-0.1.2/PKG-INFO +252 -0
  2. graphsight_langgraph-0.1.2/README.md +225 -0
  3. graphsight_langgraph-0.1.2/graphsight_langgraph.egg-info/PKG-INFO +252 -0
  4. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/pyproject.toml +2 -2
  5. graphsight_langgraph-0.1.0/PKG-INFO +0 -232
  6. graphsight_langgraph-0.1.0/README.md +0 -205
  7. graphsight_langgraph-0.1.0/graphsight_langgraph.egg-info/PKG-INFO +0 -232
  8. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/LICENSE +0 -0
  9. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph/__init__.py +0 -0
  10. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph/github_ingest.py +0 -0
  11. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph/mapper.py +0 -0
  12. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph/schema.py +0 -0
  13. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph/tracer.py +0 -0
  14. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph.egg-info/SOURCES.txt +0 -0
  15. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph.egg-info/dependency_links.txt +0 -0
  16. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph.egg-info/entry_points.txt +0 -0
  17. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph.egg-info/requires.txt +0 -0
  18. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/graphsight_langgraph.egg-info/top_level.txt +0 -0
  19. {graphsight_langgraph-0.1.0 → graphsight_langgraph-0.1.2}/setup.cfg +0 -0
@@ -0,0 +1,252 @@
1
+ Metadata-Version: 2.4
2
+ Name: graphsight-langgraph
3
+ Version: 0.1.2
4
+ Summary: X-ray for LangGraph retrieval: one callback handler captures every retriever call, score, and relational path — rendered as an interactive graph.
5
+ Author: Arush Karnatak
6
+ License: MIT
7
+ Project-URL: Repository, https://github.com/Kcodess2807/graphsight
8
+ Project-URL: Documentation, https://github.com/Kcodess2807/graphsight/tree/main/graphsight-langgraph
9
+ Keywords: langgraph,langchain,tracing,observability,rag,retrieval,agents
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Debuggers
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: langchain-core>=0.3
24
+ Provides-Extra: example
25
+ Requires-Dist: langgraph>=0.2; extra == "example"
26
+ Dynamic: license-file
27
+
28
+ # graphsight-langgraph
29
+
30
+ [![PyPI](https://img.shields.io/pypi/v/graphsight-langgraph.svg)](https://pypi.org/project/graphsight-langgraph/)
31
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://pypi.org/project/graphsight-langgraph/)
32
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://github.com/Kcodess2807/graphsight/blob/main/graphsight-langgraph/LICENSE)
33
+
34
+ **See exactly why your LangGraph agent picked the context it picked.**
35
+
36
+ Retrieval in an agent is a black box: documents go in, an answer comes out,
37
+ and when the answer is wrong you're left guessing which context misled it.
38
+ This package opens the box. One callback handler records a
39
+ [LangGraph](https://github.com/langchain-ai/langgraph) run — every node,
40
+ every retriever call, per-document scores, and (for graph-aware retrievers)
41
+ the relational paths between retrieved entities — and one command renders it
42
+ as an interactive graph in your browser.
43
+
44
+ ```
45
+ your LangGraph agent ──▶ LangGraphTracer ──▶ AgentTrace (v0.1) ──▶ graphsight viewer
46
+ (callbacks) neutral JSON interactive graph
47
+ ```
48
+
49
+ Only dependency: `langchain-core`. No engine, no backend, no account —
50
+ nothing leaves your machine.
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ pip install graphsight-langgraph # the tracer
56
+ pip install "graphsight-langgraph[example]" # + langgraph, for the GitHub CLI
57
+ pip install graphsight # the local viewer (recommended)
58
+ ```
59
+
60
+ ### Compatibility
61
+
62
+ | | |
63
+ |---|---|
64
+ | Python | ≥ 3.10 |
65
+ | `langchain-core` | ≥ 0.3 (verified against 1.5.0) |
66
+ | `langgraph` | any recent version; only needed for the `[example]` extra |
67
+ | Sync (`invoke` / `stream`) | verified |
68
+ | Async (`ainvoke` / `astream`) | same callback events; not yet covered by the verification run |
69
+
70
+ ## Quickstart: trace a GitHub repo in 60 seconds
71
+
72
+ No setup, no API keys — public repositories don't need a token:
73
+
74
+ ```bash
75
+ graphsight-github-trace langchain-ai/langgraph "who fixed the recent streaming bugs?"
76
+ graphsight graphsight_out/trace_state.json
77
+ ```
78
+
79
+ Your browser opens on a live graph of that repository's recent activity:
80
+ the PRs that matched the question, the people who authored them, the issues
81
+ they resolve — every node clickable, scores shown, execution timeline
82
+ included.
83
+
84
+ ### `graphsight-github-trace` reference
85
+
86
+ ```
87
+ graphsight-github-trace REPO [QUESTION] [options]
88
+ ```
89
+
90
+ | Argument | Default | Description |
91
+ |---|---|---|
92
+ | `REPO` | — | `owner/name`, e.g. `langchain-ai/langgraph`. |
93
+ | `QUESTION` | *"What changed recently in \<repo\>, and who drove it?"* | The question the traced retrieval answers. |
94
+ | `--token` | `$GITHUB_TOKEN` | GitHub token. Required for private repositories; raises the rate limit on public ones. |
95
+ | `--prs` | `25` | Recent pull requests to fetch. |
96
+ | `--issues` | `25` | Recent issues to fetch. |
97
+ | `--top` | `10` | Items the retrieval keeps. |
98
+ | `--out` | `graphsight_out/` | Output directory for `agent_trace.json` and `trace_state.json`. |
99
+
100
+ Method note: the CLI builds a corpus with relational edges
101
+ (`person AUTHORED pr`, `pr RESOLVES issue`, `pr TOUCHES repo`) and ranks by
102
+ **lexical overlap with 1-hop graph expansion** — deliberately simple, and
103
+ reported as such. The scores you see are exactly the scores computed;
104
+ nothing is presented as semantic similarity.
105
+
106
+ ## Tracing your own agent
107
+
108
+ The complete integration:
109
+
110
+ ```python
111
+ from graphsight_langgraph import LangGraphTracer, to_tracestate
112
+
113
+ tracer = LangGraphTracer()
114
+ result = graph.invoke(inputs, config={"callbacks": [tracer]})
115
+
116
+ trace = tracer.finish(query="why is checkout failing?", answer=result["answer"])
117
+ to_tracestate(trace) # viewer-ready dict — json.dump it, then: graphsight trace.json
118
+ ```
119
+
120
+ ### Configuration propagation (read this once)
121
+
122
+ LangChain only propagates callbacks into runnables that receive the run's
123
+ config. Inside a LangGraph node, pass the node's config through to
124
+ sub-runnables, or the tracer will record the node but not what happened
125
+ inside it:
126
+
127
+ ```python
128
+ def retrieve(state, config): # 1. accept config
129
+ docs = retriever.invoke(state["q"], config=config) # 2. pass it through
130
+ return {"docs": docs}
131
+ ```
132
+
133
+ **Symptom if you skip this:** the trace shows node spans but zero
134
+ retrievals.
135
+
136
+ ### API reference
137
+
138
+ | Name | Description |
139
+ |---|---|
140
+ | `LangGraphTracer()` | `BaseCallbackHandler` subclass. Pass via `config={"callbacks": [tracer]}` to `invoke` / `stream`. Reusable within a single run; create a fresh instance per run. |
141
+ | `tracer.finish(query=None, answer=None) -> AgentTrace` | Assembles the trace after the run: closes dangling spans, computes total latency. `query` falls back to the first retriever query seen. |
142
+ | `to_tracestate(trace) -> dict` | Maps an `AgentTrace` to the viewer's JSON contract. Serialize with `json.dump`. |
143
+ | `trace.to_dict() -> dict` | The framework-neutral `AgentTrace` (schema v0.1) for your own tooling. |
144
+ | `AgentTrace`, `Span`, `Retrieval`, `RetrievedItem`, `TraceEdge` | Plain dataclasses defining the schema; importable for custom emitters. |
145
+
146
+ ## What gets captured
147
+
148
+ | Source in the run | Captured as |
149
+ |---|---|
150
+ | Each LangGraph node execution | `Span(kind="node")` with monotonic-clock timing |
151
+ | Framework internals (`RunnableSequence`, `ChannelWrite`, `__start__`, …) | filtered out — one span per user node |
152
+ | `on_retriever_end` documents | one `RetrievedItem` per doc: id, label, kind, score, content, source |
153
+ | `Document.metadata` score keys (`score`, `relevance_score`, `similarity`, `_score`, `vector_score`) | item scores |
154
+ | `Document.metadata["edges"]` | relational edges, deduplicated per retrieval |
155
+ | LLM / tool calls | plain spans in the execution timeline |
156
+ | Edges present in a retrieval | `arm = "graph"`, else `"vector"` — detected automatically |
157
+
158
+ ### Making your retriever graph-aware
159
+
160
+ The tracer reads two optional metadata conventions from the `Document`
161
+ objects your retriever returns:
162
+
163
+ ```python
164
+ Document(
165
+ page_content="PR #4821 'fix: idempotent refund path' merged by Priya N. ...",
166
+ metadata={
167
+ "id": "pr_4821", # stable node id (falls back to a content hash)
168
+ "label": "PR #4821", # display name
169
+ "kind": "pull_request", # normalized to a viewer entity type, see below
170
+ "score": 0.94, # any recognized score key
171
+ "source": "https://github.com/acme/platform/pull/4821",
172
+ "edges": [ # optional — enables the relational view
173
+ {"source": "pr_4821", "target": "svc_checkout",
174
+ "relation": "TOUCHES", "weight": 0.9},
175
+ ],
176
+ },
177
+ )
178
+ ```
179
+
180
+ `kind` values are normalized (`pull_request → PR`, `service → Service`,
181
+ `person`/`author` → `Person`, `ticket`/`issue`/`jira` → `Ticket`,
182
+ `repo → Repo`, `library → Library`, `team → Team`, `tool → Tool`; anything
183
+ else renders as `Document`).
184
+
185
+ ### Degradation behavior
186
+
187
+ - **No edges in metadata** → a flat scored-retrieval view instead of
188
+ relational path highlighting. Still useful; not graph-aware.
189
+ - **No recognized score keys** → scores stay `None`; no score chips render.
190
+ Nothing is ever fabricated.
191
+ - The emitted `confidence.rationale` states that scores came from your
192
+ retriever and were not recomputed — an imported trace never masquerades
193
+ as an engine-computed one.
194
+
195
+ ## Schema (v0.1)
196
+
197
+ `AgentTrace` is the stable contract. Future adapters (LlamaIndex, raw
198
+ OpenTelemetry) emit the same shape and render in the same viewer.
199
+
200
+ ```jsonc
201
+ {
202
+ "schema_version": "0.1",
203
+ "framework": "langgraph",
204
+ "query": "…",
205
+ "spans": [
206
+ { "id": "…", "name": "retrieve", "kind": "node", // node | retriever | llm | tool
207
+ "parent_id": null, "start_ms": 0.0, "end_ms": 0.3, "status": "ok" }
208
+ ],
209
+ "retrievals": [
210
+ {
211
+ "span_id": "…", "query": "…",
212
+ "arm": "graph", // "vector" | "graph", auto-detected
213
+ "items": [
214
+ { "id": "pr_4821", "label": "PR #4821", "kind": "pull_request",
215
+ "score": 0.94, "vector_score": null, "graph_score": null,
216
+ "content": "…", "source_uri": "https://…", "metadata": {} }
217
+ ],
218
+ "edges": [ // optional — the relational view
219
+ { "source": "pr_4821", "target": "svc_checkout", "relation": "TOUCHES", "weight": 0.9 }
220
+ ]
221
+ }
222
+ ],
223
+ "answer": "…",
224
+ "latency_ms": 3.9
225
+ }
226
+ ```
227
+
228
+ ## Troubleshooting
229
+
230
+ | Symptom | Cause / fix |
231
+ |---|---|
232
+ | Node spans but no retrievals | Config not propagated into the node's sub-runnables — see [Configuration propagation](#configuration-propagation-read-this-once). |
233
+ | Items without scores | Your retriever doesn't write a recognized score key to `Document.metadata` — add one (`score` is simplest). |
234
+ | Flat graph, no edges | Your retriever doesn't emit `metadata["edges"]` — see [Making your retriever graph-aware](#making-your-retriever-graph-aware). |
235
+ | `GitHub API 403` from the CLI | Rate limit (60 requests/hour unauthenticated) — pass `--token` or set `GITHUB_TOKEN`. |
236
+ | Garbled output on Windows consoles | Fixed in ≥ 0.1.1; upgrade. |
237
+
238
+ ## Roadmap
239
+
240
+ In order: a **LlamaIndex adapter** emitting the same `AgentTrace`, then a
241
+ raw **OpenTelemetry span** ingestor. The schema is the contract; adapters
242
+ stay thin.
243
+
244
+ ## Links
245
+
246
+ - Source & issue tracker: [github.com/Kcodess2807/graphsight](https://github.com/Kcodess2807/graphsight)
247
+ - The viewer: [graphsight on PyPI](https://pypi.org/project/graphsight/)
248
+ - Beta test script: [BETA.md](https://github.com/Kcodess2807/graphsight/blob/main/BETA.md)
249
+
250
+ ## License
251
+
252
+ MIT © Arush Karnatak
@@ -0,0 +1,225 @@
1
+ # graphsight-langgraph
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/graphsight-langgraph.svg)](https://pypi.org/project/graphsight-langgraph/)
4
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://pypi.org/project/graphsight-langgraph/)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://github.com/Kcodess2807/graphsight/blob/main/graphsight-langgraph/LICENSE)
6
+
7
+ **See exactly why your LangGraph agent picked the context it picked.**
8
+
9
+ Retrieval in an agent is a black box: documents go in, an answer comes out,
10
+ and when the answer is wrong you're left guessing which context misled it.
11
+ This package opens the box. One callback handler records a
12
+ [LangGraph](https://github.com/langchain-ai/langgraph) run — every node,
13
+ every retriever call, per-document scores, and (for graph-aware retrievers)
14
+ the relational paths between retrieved entities — and one command renders it
15
+ as an interactive graph in your browser.
16
+
17
+ ```
18
+ your LangGraph agent ──▶ LangGraphTracer ──▶ AgentTrace (v0.1) ──▶ graphsight viewer
19
+ (callbacks) neutral JSON interactive graph
20
+ ```
21
+
22
+ Only dependency: `langchain-core`. No engine, no backend, no account —
23
+ nothing leaves your machine.
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install graphsight-langgraph # the tracer
29
+ pip install "graphsight-langgraph[example]" # + langgraph, for the GitHub CLI
30
+ pip install graphsight # the local viewer (recommended)
31
+ ```
32
+
33
+ ### Compatibility
34
+
35
+ | | |
36
+ |---|---|
37
+ | Python | ≥ 3.10 |
38
+ | `langchain-core` | ≥ 0.3 (verified against 1.5.0) |
39
+ | `langgraph` | any recent version; only needed for the `[example]` extra |
40
+ | Sync (`invoke` / `stream`) | verified |
41
+ | Async (`ainvoke` / `astream`) | same callback events; not yet covered by the verification run |
42
+
43
+ ## Quickstart: trace a GitHub repo in 60 seconds
44
+
45
+ No setup, no API keys — public repositories don't need a token:
46
+
47
+ ```bash
48
+ graphsight-github-trace langchain-ai/langgraph "who fixed the recent streaming bugs?"
49
+ graphsight graphsight_out/trace_state.json
50
+ ```
51
+
52
+ Your browser opens on a live graph of that repository's recent activity:
53
+ the PRs that matched the question, the people who authored them, the issues
54
+ they resolve — every node clickable, scores shown, execution timeline
55
+ included.
56
+
57
+ ### `graphsight-github-trace` reference
58
+
59
+ ```
60
+ graphsight-github-trace REPO [QUESTION] [options]
61
+ ```
62
+
63
+ | Argument | Default | Description |
64
+ |---|---|---|
65
+ | `REPO` | — | `owner/name`, e.g. `langchain-ai/langgraph`. |
66
+ | `QUESTION` | *"What changed recently in \<repo\>, and who drove it?"* | The question the traced retrieval answers. |
67
+ | `--token` | `$GITHUB_TOKEN` | GitHub token. Required for private repositories; raises the rate limit on public ones. |
68
+ | `--prs` | `25` | Recent pull requests to fetch. |
69
+ | `--issues` | `25` | Recent issues to fetch. |
70
+ | `--top` | `10` | Items the retrieval keeps. |
71
+ | `--out` | `graphsight_out/` | Output directory for `agent_trace.json` and `trace_state.json`. |
72
+
73
+ Method note: the CLI builds a corpus with relational edges
74
+ (`person AUTHORED pr`, `pr RESOLVES issue`, `pr TOUCHES repo`) and ranks by
75
+ **lexical overlap with 1-hop graph expansion** — deliberately simple, and
76
+ reported as such. The scores you see are exactly the scores computed;
77
+ nothing is presented as semantic similarity.
78
+
79
+ ## Tracing your own agent
80
+
81
+ The complete integration:
82
+
83
+ ```python
84
+ from graphsight_langgraph import LangGraphTracer, to_tracestate
85
+
86
+ tracer = LangGraphTracer()
87
+ result = graph.invoke(inputs, config={"callbacks": [tracer]})
88
+
89
+ trace = tracer.finish(query="why is checkout failing?", answer=result["answer"])
90
+ to_tracestate(trace) # viewer-ready dict — json.dump it, then: graphsight trace.json
91
+ ```
92
+
93
+ ### Configuration propagation (read this once)
94
+
95
+ LangChain only propagates callbacks into runnables that receive the run's
96
+ config. Inside a LangGraph node, pass the node's config through to
97
+ sub-runnables, or the tracer will record the node but not what happened
98
+ inside it:
99
+
100
+ ```python
101
+ def retrieve(state, config): # 1. accept config
102
+ docs = retriever.invoke(state["q"], config=config) # 2. pass it through
103
+ return {"docs": docs}
104
+ ```
105
+
106
+ **Symptom if you skip this:** the trace shows node spans but zero
107
+ retrievals.
108
+
109
+ ### API reference
110
+
111
+ | Name | Description |
112
+ |---|---|
113
+ | `LangGraphTracer()` | `BaseCallbackHandler` subclass. Pass via `config={"callbacks": [tracer]}` to `invoke` / `stream`. Reusable within a single run; create a fresh instance per run. |
114
+ | `tracer.finish(query=None, answer=None) -> AgentTrace` | Assembles the trace after the run: closes dangling spans, computes total latency. `query` falls back to the first retriever query seen. |
115
+ | `to_tracestate(trace) -> dict` | Maps an `AgentTrace` to the viewer's JSON contract. Serialize with `json.dump`. |
116
+ | `trace.to_dict() -> dict` | The framework-neutral `AgentTrace` (schema v0.1) for your own tooling. |
117
+ | `AgentTrace`, `Span`, `Retrieval`, `RetrievedItem`, `TraceEdge` | Plain dataclasses defining the schema; importable for custom emitters. |
118
+
119
+ ## What gets captured
120
+
121
+ | Source in the run | Captured as |
122
+ |---|---|
123
+ | Each LangGraph node execution | `Span(kind="node")` with monotonic-clock timing |
124
+ | Framework internals (`RunnableSequence`, `ChannelWrite`, `__start__`, …) | filtered out — one span per user node |
125
+ | `on_retriever_end` documents | one `RetrievedItem` per doc: id, label, kind, score, content, source |
126
+ | `Document.metadata` score keys (`score`, `relevance_score`, `similarity`, `_score`, `vector_score`) | item scores |
127
+ | `Document.metadata["edges"]` | relational edges, deduplicated per retrieval |
128
+ | LLM / tool calls | plain spans in the execution timeline |
129
+ | Edges present in a retrieval | `arm = "graph"`, else `"vector"` — detected automatically |
130
+
131
+ ### Making your retriever graph-aware
132
+
133
+ The tracer reads two optional metadata conventions from the `Document`
134
+ objects your retriever returns:
135
+
136
+ ```python
137
+ Document(
138
+ page_content="PR #4821 'fix: idempotent refund path' merged by Priya N. ...",
139
+ metadata={
140
+ "id": "pr_4821", # stable node id (falls back to a content hash)
141
+ "label": "PR #4821", # display name
142
+ "kind": "pull_request", # normalized to a viewer entity type, see below
143
+ "score": 0.94, # any recognized score key
144
+ "source": "https://github.com/acme/platform/pull/4821",
145
+ "edges": [ # optional — enables the relational view
146
+ {"source": "pr_4821", "target": "svc_checkout",
147
+ "relation": "TOUCHES", "weight": 0.9},
148
+ ],
149
+ },
150
+ )
151
+ ```
152
+
153
+ `kind` values are normalized (`pull_request → PR`, `service → Service`,
154
+ `person`/`author` → `Person`, `ticket`/`issue`/`jira` → `Ticket`,
155
+ `repo → Repo`, `library → Library`, `team → Team`, `tool → Tool`; anything
156
+ else renders as `Document`).
157
+
158
+ ### Degradation behavior
159
+
160
+ - **No edges in metadata** → a flat scored-retrieval view instead of
161
+ relational path highlighting. Still useful; not graph-aware.
162
+ - **No recognized score keys** → scores stay `None`; no score chips render.
163
+ Nothing is ever fabricated.
164
+ - The emitted `confidence.rationale` states that scores came from your
165
+ retriever and were not recomputed — an imported trace never masquerades
166
+ as an engine-computed one.
167
+
168
+ ## Schema (v0.1)
169
+
170
+ `AgentTrace` is the stable contract. Future adapters (LlamaIndex, raw
171
+ OpenTelemetry) emit the same shape and render in the same viewer.
172
+
173
+ ```jsonc
174
+ {
175
+ "schema_version": "0.1",
176
+ "framework": "langgraph",
177
+ "query": "…",
178
+ "spans": [
179
+ { "id": "…", "name": "retrieve", "kind": "node", // node | retriever | llm | tool
180
+ "parent_id": null, "start_ms": 0.0, "end_ms": 0.3, "status": "ok" }
181
+ ],
182
+ "retrievals": [
183
+ {
184
+ "span_id": "…", "query": "…",
185
+ "arm": "graph", // "vector" | "graph", auto-detected
186
+ "items": [
187
+ { "id": "pr_4821", "label": "PR #4821", "kind": "pull_request",
188
+ "score": 0.94, "vector_score": null, "graph_score": null,
189
+ "content": "…", "source_uri": "https://…", "metadata": {} }
190
+ ],
191
+ "edges": [ // optional — the relational view
192
+ { "source": "pr_4821", "target": "svc_checkout", "relation": "TOUCHES", "weight": 0.9 }
193
+ ]
194
+ }
195
+ ],
196
+ "answer": "…",
197
+ "latency_ms": 3.9
198
+ }
199
+ ```
200
+
201
+ ## Troubleshooting
202
+
203
+ | Symptom | Cause / fix |
204
+ |---|---|
205
+ | Node spans but no retrievals | Config not propagated into the node's sub-runnables — see [Configuration propagation](#configuration-propagation-read-this-once). |
206
+ | Items without scores | Your retriever doesn't write a recognized score key to `Document.metadata` — add one (`score` is simplest). |
207
+ | Flat graph, no edges | Your retriever doesn't emit `metadata["edges"]` — see [Making your retriever graph-aware](#making-your-retriever-graph-aware). |
208
+ | `GitHub API 403` from the CLI | Rate limit (60 requests/hour unauthenticated) — pass `--token` or set `GITHUB_TOKEN`. |
209
+ | Garbled output on Windows consoles | Fixed in ≥ 0.1.1; upgrade. |
210
+
211
+ ## Roadmap
212
+
213
+ In order: a **LlamaIndex adapter** emitting the same `AgentTrace`, then a
214
+ raw **OpenTelemetry span** ingestor. The schema is the contract; adapters
215
+ stay thin.
216
+
217
+ ## Links
218
+
219
+ - Source & issue tracker: [github.com/Kcodess2807/graphsight](https://github.com/Kcodess2807/graphsight)
220
+ - The viewer: [graphsight on PyPI](https://pypi.org/project/graphsight/)
221
+ - Beta test script: [BETA.md](https://github.com/Kcodess2807/graphsight/blob/main/BETA.md)
222
+
223
+ ## License
224
+
225
+ MIT © Arush Karnatak