|
3551b80…
|
noreply
|
1 |
# Knowledge Graphs |
|
3551b80…
|
noreply
|
2 |
|
|
3551b80…
|
noreply
|
3 |
PlanOpticon builds structured knowledge graphs from video analyses, document ingestion, and other content sources. A knowledge graph captures **entities** (people, technologies, concepts, organizations) and the **relationships** between them, providing a queryable representation of everything discussed or presented in your source material. |
|
3551b80…
|
noreply
|
4 |
|
|
3551b80…
|
noreply
|
5 |
--- |
|
3551b80…
|
noreply
|
6 |
|
|
3551b80…
|
noreply
|
7 |
## Storage |
|
3551b80…
|
noreply
|
8 |
|
|
3551b80…
|
noreply
|
9 |
Knowledge graphs are stored as SQLite databases (`knowledge_graph.db`) using Python's built-in `sqlite3` module. This means: |
|
3551b80…
|
noreply
|
10 |
|
|
3551b80…
|
noreply
|
11 |
- **Zero external dependencies.** No database server to install or manage. |
|
3551b80…
|
noreply
|
12 |
- **Single-file portability.** Copy the `.db` file to share a knowledge graph. |
|
3551b80…
|
noreply
|
13 |
- **WAL mode.** SQLite Write-Ahead Logging is enabled for concurrent read performance. |
|
3551b80…
|
noreply
|
14 |
- **JSON fallback.** Knowledge graphs can also be saved as `knowledge_graph.json` for interoperability, though SQLite is preferred for performance and querying. |
|
3551b80…
|
noreply
|
15 |
|
|
3551b80…
|
noreply
|
16 |
### Database Schema |
|
3551b80…
|
noreply
|
17 |
|
|
3551b80…
|
noreply
|
18 |
The SQLite store uses the following tables: |
|
3551b80…
|
noreply
|
19 |
|
|
3551b80…
|
noreply
|
20 |
| Table | Purpose | |
|
3551b80…
|
noreply
|
21 |
|---|---| |
|
3551b80…
|
noreply
|
22 |
| `entities` | Core entity records with name, type, descriptions, source, and arbitrary properties | |
|
3551b80…
|
noreply
|
23 |
| `occurrences` | Where and when each entity was mentioned (source, timestamp, text snippet) | |
|
3551b80…
|
noreply
|
24 |
| `relationships` | Directed edges between entities with type, content source, timestamp, and properties | |
|
3551b80…
|
noreply
|
25 |
| `sources` | Registered content sources with provenance metadata (source type, title, path, URL, MIME type, ingestion timestamp) | |
|
3551b80…
|
noreply
|
26 |
| `source_locations` | Links between sources and specific entities/relationships, with location details (timestamp, page, section, line range, text snippet) | |
|
3551b80…
|
noreply
|
27 |
|
|
3551b80…
|
noreply
|
28 |
All entity lookups are case-insensitive (indexed on `name_lower`). Entities and relationships are indexed on their source and target fields for efficient traversal. |
|
3551b80…
|
noreply
|
29 |
|
|
3551b80…
|
noreply
|
30 |
### Storage Backends |
|
3551b80…
|
noreply
|
31 |
|
|
3551b80…
|
noreply
|
32 |
PlanOpticon supports two storage backends, selected automatically: |
|
3551b80…
|
noreply
|
33 |
|
|
3551b80…
|
noreply
|
34 |
| Backend | When Used | Persistence | |
|
3551b80…
|
noreply
|
35 |
|---|---|---| |
|
3551b80…
|
noreply
|
36 |
| `SQLiteStore` | When a `db_path` is provided | Persistent on disk | |
|
3551b80…
|
noreply
|
37 |
| `InMemoryStore` | When no path is given, or as fallback | In-memory only | |
|
3551b80…
|
noreply
|
38 |
|
|
3551b80…
|
noreply
|
39 |
Both backends implement the same `GraphStore` abstract interface, so all query and manipulation code works identically regardless of backend. |
|
3551b80…
|
noreply
|
40 |
|
|
3551b80…
|
noreply
|
41 |
```python |
|
3551b80…
|
noreply
|
42 |
from video_processor.integrators.graph_store import create_store |
|
3551b80…
|
noreply
|
43 |
|
|
3551b80…
|
noreply
|
44 |
# Persistent SQLite store |
|
3551b80…
|
noreply
|
45 |
store = create_store("/path/to/knowledge_graph.db") |
|
3551b80…
|
noreply
|
46 |
|
|
3551b80…
|
noreply
|
47 |
# In-memory store (for temporary operations) |
|
3551b80…
|
noreply
|
48 |
store = create_store() |
|
3551b80…
|
noreply
|
49 |
``` |
|
3551b80…
|
noreply
|
50 |
|
|
3551b80…
|
noreply
|
51 |
--- |
|
3551b80…
|
noreply
|
52 |
|
|
3551b80…
|
noreply
|
53 |
## Entity Types |
|
3551b80…
|
noreply
|
54 |
|
|
3551b80…
|
noreply
|
55 |
Entities extracted from content are assigned one of the following base types: |
|
3551b80…
|
noreply
|
56 |
|
|
3551b80…
|
noreply
|
57 |
| Type | Description | Specificity Rank | |
|
3551b80…
|
noreply
|
58 |
|---|---|---| |
|
3551b80…
|
noreply
|
59 |
| `person` | People mentioned or participating | 3 (highest) | |
|
3551b80…
|
noreply
|
60 |
| `technology` | Tools, languages, frameworks, platforms | 3 | |
|
3551b80…
|
noreply
|
61 |
| `organization` | Companies, teams, departments | 2 | |
|
3551b80…
|
noreply
|
62 |
| `time` | Dates, deadlines, time references | 1 | |
|
3551b80…
|
noreply
|
63 |
| `diagram` | Visual diagrams extracted from video frames | 1 | |
|
3551b80…
|
noreply
|
64 |
| `concept` | General concepts, topics, ideas (default) | 0 (lowest) | |
|
3551b80…
|
noreply
|
65 |
|
|
3551b80…
|
noreply
|
66 |
The specificity rank is used during merge operations: when two entities are matched as duplicates, the more specific type wins (e.g., `technology` overrides `concept`). |
|
3551b80…
|
noreply
|
67 |
|
|
3551b80…
|
noreply
|
68 |
### Planning Taxonomy |
|
3551b80…
|
noreply
|
69 |
|
|
3551b80…
|
noreply
|
70 |
Beyond the base entity types, PlanOpticon includes a planning taxonomy for classifying entities into project-planning categories. The `TaxonomyClassifier` maps extracted entities into these types: |
|
3551b80…
|
noreply
|
71 |
|
|
3551b80…
|
noreply
|
72 |
| Planning Type | Keywords Matched | |
|
3551b80…
|
noreply
|
73 |
|---|---| |
|
3551b80…
|
noreply
|
74 |
| `goal` | goal, objective, aim, target outcome | |
|
3551b80…
|
noreply
|
75 |
| `requirement` | must, should, requirement, need, required | |
|
3551b80…
|
noreply
|
76 |
| `constraint` | constraint, limitation, restrict, cannot, must not | |
|
3551b80…
|
noreply
|
77 |
| `decision` | decided, decision, chose, selected, agreed | |
|
3551b80…
|
noreply
|
78 |
| `risk` | risk, concern, worry, danger, threat | |
|
3551b80…
|
noreply
|
79 |
| `assumption` | assume, assumption, expecting, presume | |
|
3551b80…
|
noreply
|
80 |
| `dependency` | depends, dependency, relies on, prerequisite, blocked | |
|
3551b80…
|
noreply
|
81 |
| `milestone` | milestone, deadline, deliverable, release, launch | |
|
3551b80…
|
noreply
|
82 |
| `task` | task, todo, action item, work item, implement | |
|
3551b80…
|
noreply
|
83 |
| `feature` | feature, capability, functionality | |
|
3551b80…
|
noreply
|
84 |
|
|
3551b80…
|
noreply
|
85 |
Classification works in two stages: |
|
3551b80…
|
noreply
|
86 |
|
|
3551b80…
|
noreply
|
87 |
1. **Heuristic classification.** Entity descriptions are scanned for the keywords listed above. First match wins. |
|
3551b80…
|
noreply
|
88 |
2. **LLM refinement.** If an LLM provider is available, entities are sent to the LLM for more nuanced classification with priority assignment (`high`, `medium`, `low`). LLM results override heuristic results on conflicts. |
|
3551b80…
|
noreply
|
89 |
|
|
3551b80…
|
noreply
|
90 |
Classified entities are used by planning agent skills (project_plan, prd, roadmap, task_breakdown) to produce targeted, context-aware artifacts. |
|
3551b80…
|
noreply
|
91 |
|
|
3551b80…
|
noreply
|
92 |
--- |
|
3551b80…
|
noreply
|
93 |
|
|
3551b80…
|
noreply
|
94 |
## Relationship Types |
|
3551b80…
|
noreply
|
95 |
|
|
3551b80…
|
noreply
|
96 |
Relationships are directed edges between entities. The `type` field is a free-text string determined by the LLM during extraction. Common relationship types include: |
|
3551b80…
|
noreply
|
97 |
|
|
3551b80…
|
noreply
|
98 |
- `related_to` (default) |
|
3551b80…
|
noreply
|
99 |
- `works_with` |
|
3551b80…
|
noreply
|
100 |
- `uses` |
|
3551b80…
|
noreply
|
101 |
- `depends_on` |
|
3551b80…
|
noreply
|
102 |
- `proposed` |
|
3551b80…
|
noreply
|
103 |
- `discussed_by` |
|
3551b80…
|
noreply
|
104 |
- `employed_by` |
|
3551b80…
|
noreply
|
105 |
- `collaborates_with` |
|
3551b80…
|
noreply
|
106 |
- `expert_in` |
|
3551b80…
|
noreply
|
107 |
|
|
3551b80…
|
noreply
|
108 |
### Typed Relationships |
|
3551b80…
|
noreply
|
109 |
|
|
3551b80…
|
noreply
|
110 |
The `add_typed_relationship()` method creates edges with custom labels and optional properties, enabling richer graph semantics: |
|
3551b80…
|
noreply
|
111 |
|
|
3551b80…
|
noreply
|
112 |
```python |
|
3551b80…
|
noreply
|
113 |
store.add_typed_relationship( |
|
3551b80…
|
noreply
|
114 |
source="Authentication Service", |
|
3551b80…
|
noreply
|
115 |
target="PostgreSQL", |
|
3551b80…
|
noreply
|
116 |
edge_label="USES_SYSTEM", |
|
3551b80…
|
noreply
|
117 |
properties={"purpose": "user credential storage", "version": "15"}, |
|
3551b80…
|
noreply
|
118 |
) |
|
3551b80…
|
noreply
|
119 |
``` |
|
3551b80…
|
noreply
|
120 |
|
|
3551b80…
|
noreply
|
121 |
### Relationship Checks |
|
3551b80…
|
noreply
|
122 |
|
|
3551b80…
|
noreply
|
123 |
You can check whether a relationship exists between two entities: |
|
3551b80…
|
noreply
|
124 |
|
|
3551b80…
|
noreply
|
125 |
```python |
|
3551b80…
|
noreply
|
126 |
# Check for any relationship |
|
3551b80…
|
noreply
|
127 |
store.has_relationship("Alice", "Kubernetes") |
|
3551b80…
|
noreply
|
128 |
|
|
3551b80…
|
noreply
|
129 |
# Check for a specific relationship type |
|
3551b80…
|
noreply
|
130 |
store.has_relationship("Alice", "Kubernetes", edge_label="expert_in") |
|
3551b80…
|
noreply
|
131 |
``` |
|
3551b80…
|
noreply
|
132 |
|
|
3551b80…
|
noreply
|
133 |
--- |
|
3551b80…
|
noreply
|
134 |
|
|
3551b80…
|
noreply
|
135 |
## Building a Knowledge Graph |
|
3551b80…
|
noreply
|
136 |
|
|
3551b80…
|
noreply
|
137 |
### From Video Analysis |
|
3551b80…
|
noreply
|
138 |
|
|
3551b80…
|
noreply
|
139 |
The primary path for building a knowledge graph is through video analysis. When you run `planopticon analyze`, the pipeline extracts entities and relationships from: |
|
3551b80…
|
noreply
|
140 |
|
|
3551b80…
|
noreply
|
141 |
- **Transcript segments** -- batched in groups of 10 for efficient API usage, with speaker identification |
|
3551b80…
|
noreply
|
142 |
- **Diagram content** -- text extracted from visual diagrams detected in video frames |
|
3551b80…
|
noreply
|
143 |
|
|
3551b80…
|
noreply
|
144 |
```bash |
|
3551b80…
|
noreply
|
145 |
planopticon analyze -i meeting.mp4 -o results/ |
|
3551b80…
|
noreply
|
146 |
# Creates results/knowledge_graph.db |
|
3551b80…
|
noreply
|
147 |
``` |
|
3551b80…
|
noreply
|
148 |
|
|
3551b80…
|
noreply
|
149 |
### From Document Ingestion |
|
3551b80…
|
noreply
|
150 |
|
|
3551b80…
|
noreply
|
151 |
Documents (Markdown, PDF, DOCX) can be ingested directly into a knowledge graph: |
|
3551b80…
|
noreply
|
152 |
|
|
3551b80…
|
noreply
|
153 |
```bash |
|
3551b80…
|
noreply
|
154 |
# Ingest a single file |
|
3551b80…
|
noreply
|
155 |
planopticon ingest -i requirements.pdf -o results/ |
|
3551b80…
|
noreply
|
156 |
|
|
3551b80…
|
noreply
|
157 |
# Ingest a directory recursively |
|
3551b80…
|
noreply
|
158 |
planopticon ingest -i docs/ -o results/ --recursive |
|
3551b80…
|
noreply
|
159 |
|
|
3551b80…
|
noreply
|
160 |
# Ingest into an existing knowledge graph |
|
3551b80…
|
noreply
|
161 |
planopticon ingest -i notes.md --db results/knowledge_graph.db |
|
3551b80…
|
noreply
|
162 |
``` |
|
3551b80…
|
noreply
|
163 |
|
|
3551b80…
|
noreply
|
164 |
### From Batch Processing |
|
3551b80…
|
noreply
|
165 |
|
|
3551b80…
|
noreply
|
166 |
Multiple videos can be processed in batch mode, with all results merged into a single knowledge graph: |
|
3551b80…
|
noreply
|
167 |
|
|
3551b80…
|
noreply
|
168 |
```bash |
|
3551b80…
|
noreply
|
169 |
planopticon batch -i videos/ -o results/ |
|
3551b80…
|
noreply
|
170 |
``` |
|
3551b80…
|
noreply
|
171 |
|
|
3551b80…
|
noreply
|
172 |
### Programmatic Construction |
|
3551b80…
|
noreply
|
173 |
|
|
3551b80…
|
noreply
|
174 |
```python |
|
3551b80…
|
noreply
|
175 |
from video_processor.integrators.knowledge_graph import KnowledgeGraph |
|
3551b80…
|
noreply
|
176 |
|
|
3551b80…
|
noreply
|
177 |
# Create a new knowledge graph with LLM extraction |
|
3551b80…
|
noreply
|
178 |
from video_processor.providers.manager import ProviderManager |
|
3551b80…
|
noreply
|
179 |
pm = ProviderManager() |
|
3551b80…
|
noreply
|
180 |
kg = KnowledgeGraph(provider_manager=pm, db_path="knowledge_graph.db") |
|
3551b80…
|
noreply
|
181 |
|
|
3551b80…
|
noreply
|
182 |
# Add content (entities and relationships are extracted by LLM) |
|
3551b80…
|
noreply
|
183 |
kg.add_content( |
|
3551b80…
|
noreply
|
184 |
text="Alice proposed using Kubernetes for container orchestration.", |
|
3551b80…
|
noreply
|
185 |
source="meeting_notes", |
|
3551b80…
|
noreply
|
186 |
timestamp=120.5, |
|
3551b80…
|
noreply
|
187 |
) |
|
3551b80…
|
noreply
|
188 |
|
|
3551b80…
|
noreply
|
189 |
# Process a full transcript |
|
3551b80…
|
noreply
|
190 |
kg.process_transcript(transcript_data, batch_size=10) |
|
3551b80…
|
noreply
|
191 |
|
|
3551b80…
|
noreply
|
192 |
# Process diagram results |
|
3551b80…
|
noreply
|
193 |
kg.process_diagrams(diagram_results) |
|
3551b80…
|
noreply
|
194 |
|
|
3551b80…
|
noreply
|
195 |
# Save |
|
3551b80…
|
noreply
|
196 |
kg.save("knowledge_graph.db") |
|
3551b80…
|
noreply
|
197 |
``` |
|
3551b80…
|
noreply
|
198 |
|
|
3551b80…
|
noreply
|
199 |
--- |
|
3551b80…
|
noreply
|
200 |
|
|
3551b80…
|
noreply
|
201 |
## Merge and Deduplication |
|
3551b80…
|
noreply
|
202 |
|
|
3551b80…
|
noreply
|
203 |
When combining knowledge graphs from multiple sources, PlanOpticon performs intelligent merge with deduplication. |
|
3551b80…
|
noreply
|
204 |
|
|
3551b80…
|
noreply
|
205 |
### Fuzzy Name Matching |
|
3551b80…
|
noreply
|
206 |
|
|
3551b80…
|
noreply
|
207 |
Entity names are compared using Python's `SequenceMatcher` with a threshold of 0.85. This means "Kubernetes" and "kubernetes" are matched exactly (case-insensitive), while "React.js" and "ReactJS" may be matched as duplicates if their similarity ratio meets the threshold. |
|
3551b80…
|
noreply
|
208 |
|
|
3551b80…
|
noreply
|
209 |
### Type Conflict Resolution |
|
3551b80…
|
noreply
|
210 |
|
|
3551b80…
|
noreply
|
211 |
When two entities match but have different types, the more specific type wins based on the specificity ranking: |
|
3551b80…
|
noreply
|
212 |
|
|
3551b80…
|
noreply
|
213 |
| Scenario | Result | |
|
3551b80…
|
noreply
|
214 |
|---|---| |
|
3551b80…
|
noreply
|
215 |
| `concept` vs `technology` | `technology` wins (rank 3 > rank 0) | |
|
3551b80…
|
noreply
|
216 |
| `person` vs `concept` | `person` wins (rank 3 > rank 0) | |
|
3551b80…
|
noreply
|
217 |
| `organization` vs `concept` | `organization` wins (rank 2 > rank 0) | |
|
3551b80…
|
noreply
|
218 |
| `person` vs `technology` | Keeps whichever was first (equal rank) | |
|
3551b80…
|
noreply
|
219 |
|
|
3551b80…
|
noreply
|
220 |
### Provenance Tracking |
|
3551b80…
|
noreply
|
221 |
|
|
3551b80…
|
noreply
|
222 |
Merged entities receive a `merged_from:<original_name>` description entry, preserving the audit trail of which entities were unified. |
|
3551b80…
|
noreply
|
223 |
|
|
3551b80…
|
noreply
|
224 |
### Programmatic Merge |
|
3551b80…
|
noreply
|
225 |
|
|
3551b80…
|
noreply
|
226 |
```python |
|
3551b80…
|
noreply
|
227 |
from video_processor.integrators.knowledge_graph import KnowledgeGraph |
|
3551b80…
|
noreply
|
228 |
|
|
3551b80…
|
noreply
|
229 |
# Load two knowledge graphs |
|
3551b80…
|
noreply
|
230 |
kg1 = KnowledgeGraph(db_path="project_a.db") |
|
3551b80…
|
noreply
|
231 |
kg2 = KnowledgeGraph(db_path="project_b.db") |
|
3551b80…
|
noreply
|
232 |
|
|
3551b80…
|
noreply
|
233 |
# Merge kg2 into kg1 |
|
3551b80…
|
noreply
|
234 |
kg1.merge(kg2) |
|
3551b80…
|
noreply
|
235 |
|
|
3551b80…
|
noreply
|
236 |
# Save the merged result |
|
3551b80…
|
noreply
|
237 |
kg1.save("merged.db") |
|
3551b80…
|
noreply
|
238 |
``` |
|
3551b80…
|
noreply
|
239 |
|
|
3551b80…
|
noreply
|
240 |
The merge operation also copies all registered sources and occurrences, so provenance information is preserved across merges. |
|
3551b80…
|
noreply
|
241 |
|
|
3551b80…
|
noreply
|
242 |
--- |
|
3551b80…
|
noreply
|
243 |
|
|
3551b80…
|
noreply
|
244 |
## Querying |
|
3551b80…
|
noreply
|
245 |
|
|
3551b80…
|
noreply
|
246 |
PlanOpticon provides two query modes: direct mode (no LLM required) and agentic mode (LLM-powered natural language). |
|
3551b80…
|
noreply
|
247 |
|
|
3551b80…
|
noreply
|
248 |
### Direct Mode |
|
3551b80…
|
noreply
|
249 |
|
|
3551b80…
|
noreply
|
250 |
Direct mode queries are fast, deterministic, and require no API key. They are the right choice for structured lookups. |
|
3551b80…
|
noreply
|
251 |
|
|
3551b80…
|
noreply
|
252 |
#### Stats |
|
3551b80…
|
noreply
|
253 |
|
|
3551b80…
|
noreply
|
254 |
Return entity count, relationship count, and entity type breakdown: |
|
3551b80…
|
noreply
|
255 |
|
|
3551b80…
|
noreply
|
256 |
```bash |
|
3551b80…
|
noreply
|
257 |
planopticon query |
|
3551b80…
|
noreply
|
258 |
``` |
|
3551b80…
|
noreply
|
259 |
|
|
3551b80…
|
noreply
|
260 |
```python |
|
3551b80…
|
noreply
|
261 |
engine.stats() |
|
3551b80…
|
noreply
|
262 |
# QueryResult with data: { |
|
3551b80…
|
noreply
|
263 |
# "entity_count": 42, |
|
3551b80…
|
noreply
|
264 |
# "relationship_count": 87, |
|
3551b80…
|
noreply
|
265 |
# "entity_types": {"technology": 15, "person": 12, ...} |
|
3551b80…
|
noreply
|
266 |
# } |
|
3551b80…
|
noreply
|
267 |
``` |
|
3551b80…
|
noreply
|
268 |
|
|
3551b80…
|
noreply
|
269 |
#### Entities |
|
3551b80…
|
noreply
|
270 |
|
|
3551b80…
|
noreply
|
271 |
Filter entities by name substring and/or type: |
|
3551b80…
|
noreply
|
272 |
|
|
3551b80…
|
noreply
|
273 |
```bash |
|
3551b80…
|
noreply
|
274 |
planopticon query "entities --type technology" |
|
3551b80…
|
noreply
|
275 |
planopticon query "entities --name python" |
|
3551b80…
|
noreply
|
276 |
``` |
|
3551b80…
|
noreply
|
277 |
|
|
3551b80…
|
noreply
|
278 |
```python |
|
3551b80…
|
noreply
|
279 |
engine.entities(entity_type="technology") |
|
3551b80…
|
noreply
|
280 |
engine.entities(name="python") |
|
3551b80…
|
noreply
|
281 |
engine.entities(name="auth", entity_type="concept", limit=10) |
|
3551b80…
|
noreply
|
282 |
``` |
|
3551b80…
|
noreply
|
283 |
|
|
3551b80…
|
noreply
|
284 |
All filtering is case-insensitive. Results are capped at 50 by default (configurable via `limit`). |
|
3551b80…
|
noreply
|
285 |
|
|
3551b80…
|
noreply
|
286 |
#### Neighbors |
|
3551b80…
|
noreply
|
287 |
|
|
3551b80…
|
noreply
|
288 |
Get an entity and all directly connected nodes and relationships: |
|
3551b80…
|
noreply
|
289 |
|
|
3551b80…
|
noreply
|
290 |
```bash |
|
3551b80…
|
noreply
|
291 |
planopticon query "neighbors Alice" |
|
3551b80…
|
noreply
|
292 |
``` |
|
3551b80…
|
noreply
|
293 |
|
|
3551b80…
|
noreply
|
294 |
```python |
|
3551b80…
|
noreply
|
295 |
engine.neighbors("Alice", depth=1) |
|
3551b80…
|
noreply
|
296 |
``` |
|
3551b80…
|
noreply
|
297 |
|
|
3551b80…
|
noreply
|
298 |
The `depth` parameter controls how many hops to traverse (default 1). The result includes both entity objects and relationship objects. |
|
3551b80…
|
noreply
|
299 |
|
|
3551b80…
|
noreply
|
300 |
#### Relationships |
|
3551b80…
|
noreply
|
301 |
|
|
3551b80…
|
noreply
|
302 |
Filter relationships by source, target, and/or type: |
|
3551b80…
|
noreply
|
303 |
|
|
3551b80…
|
noreply
|
304 |
```bash |
|
3551b80…
|
noreply
|
305 |
planopticon query "relationships --source Alice" |
|
3551b80…
|
noreply
|
306 |
``` |
|
3551b80…
|
noreply
|
307 |
|
|
3551b80…
|
noreply
|
308 |
```python |
|
3551b80…
|
noreply
|
309 |
engine.relationships(source="Alice") |
|
3551b80…
|
noreply
|
310 |
engine.relationships(target="Kubernetes", rel_type="uses") |
|
3551b80…
|
noreply
|
311 |
``` |
|
3551b80…
|
noreply
|
312 |
|
|
3551b80…
|
noreply
|
313 |
#### Sources |
|
3551b80…
|
noreply
|
314 |
|
|
3551b80…
|
noreply
|
315 |
List all registered content sources: |
|
3551b80…
|
noreply
|
316 |
|
|
3551b80…
|
noreply
|
317 |
```python |
|
3551b80…
|
noreply
|
318 |
engine.sources() |
|
3551b80…
|
noreply
|
319 |
``` |
|
3551b80…
|
noreply
|
320 |
|
|
3551b80…
|
noreply
|
321 |
#### Provenance |
|
3551b80…
|
noreply
|
322 |
|
|
3551b80…
|
noreply
|
323 |
Get all source locations for a specific entity, showing exactly where it was mentioned: |
|
3551b80…
|
noreply
|
324 |
|
|
3551b80…
|
noreply
|
325 |
```python |
|
3551b80…
|
noreply
|
326 |
engine.provenance("Kubernetes") |
|
3551b80…
|
noreply
|
327 |
# Returns source locations with timestamps, pages, sections, and text snippets |
|
3551b80…
|
noreply
|
328 |
``` |
|
3551b80…
|
noreply
|
329 |
|
|
3551b80…
|
noreply
|
330 |
#### Raw SQL |
|
3551b80…
|
noreply
|
331 |
|
|
3551b80…
|
noreply
|
332 |
Execute arbitrary SQL against the SQLite backend (SQLite stores only): |
|
3551b80…
|
noreply
|
333 |
|
|
3551b80…
|
noreply
|
334 |
```python |
|
3551b80…
|
noreply
|
335 |
engine.sql("SELECT name, type FROM entities WHERE type = 'technology' ORDER BY name") |
|
3551b80…
|
noreply
|
336 |
``` |
|
3551b80…
|
noreply
|
337 |
|
|
3551b80…
|
noreply
|
338 |
### Agentic Mode |
|
3551b80…
|
noreply
|
339 |
|
|
3551b80…
|
noreply
|
340 |
Agentic mode accepts natural-language questions and uses the LLM to plan and execute queries. It requires a configured LLM provider. |
|
3551b80…
|
noreply
|
341 |
|
|
3551b80…
|
noreply
|
342 |
```bash |
|
3551b80…
|
noreply
|
343 |
planopticon query "What technologies were discussed?" |
|
3551b80…
|
noreply
|
344 |
planopticon query "Who are the key people mentioned?" |
|
3551b80…
|
noreply
|
345 |
planopticon query "What depends on the authentication service?" |
|
3551b80…
|
noreply
|
346 |
``` |
|
3551b80…
|
noreply
|
347 |
|
|
3551b80…
|
noreply
|
348 |
The agentic query pipeline: |
|
3551b80…
|
noreply
|
349 |
|
|
3551b80…
|
noreply
|
350 |
1. **Plan.** The LLM receives graph stats and available actions (entities, relationships, neighbors, stats). It selects exactly one action and its parameters. |
|
3551b80…
|
noreply
|
351 |
2. **Execute.** The chosen action is run through the direct-mode engine. |
|
3551b80…
|
noreply
|
352 |
3. **Synthesize.** The LLM receives the raw query results and the original question, then produces a concise natural-language answer. |
|
3551b80…
|
noreply
|
353 |
|
|
3551b80…
|
noreply
|
354 |
This design ensures the LLM never generates arbitrary code -- it only selects from a fixed set of known query actions. |
|
3551b80…
|
noreply
|
355 |
|
|
3551b80…
|
noreply
|
356 |
```bash |
|
3551b80…
|
noreply
|
357 |
# Requires an API key |
|
3551b80…
|
noreply
|
358 |
planopticon query "What technologies were discussed?" -p openai |
|
3551b80…
|
noreply
|
359 |
|
|
3551b80…
|
noreply
|
360 |
# Use the interactive REPL for multiple queries |
|
3551b80…
|
noreply
|
361 |
planopticon query -I |
|
3551b80…
|
noreply
|
362 |
``` |
|
3551b80…
|
noreply
|
363 |
|
|
3551b80…
|
noreply
|
364 |
--- |
|
3551b80…
|
noreply
|
365 |
|
|
3551b80…
|
noreply
|
366 |
## Graph Query Engine Python API |
|
3551b80…
|
noreply
|
367 |
|
|
3551b80…
|
noreply
|
368 |
The `GraphQueryEngine` class provides the programmatic interface for all query operations. |
|
3551b80…
|
noreply
|
369 |
|
|
3551b80…
|
noreply
|
370 |
### Initialization |
|
3551b80…
|
noreply
|
371 |
|
|
3551b80…
|
noreply
|
372 |
```python |
|
3551b80…
|
noreply
|
373 |
from video_processor.integrators.graph_query import GraphQueryEngine |
|
3551b80…
|
noreply
|
374 |
from video_processor.integrators.graph_discovery import find_nearest_graph |
|
3551b80…
|
noreply
|
375 |
|
|
3551b80…
|
noreply
|
376 |
# From a .db file |
|
3551b80…
|
noreply
|
377 |
path = find_nearest_graph() |
|
3551b80…
|
noreply
|
378 |
engine = GraphQueryEngine.from_db_path(path) |
|
3551b80…
|
noreply
|
379 |
|
|
3551b80…
|
noreply
|
380 |
# From a .json file |
|
3551b80…
|
noreply
|
381 |
engine = GraphQueryEngine.from_json_path("knowledge_graph.json") |
|
3551b80…
|
noreply
|
382 |
|
|
3551b80…
|
noreply
|
383 |
# With an LLM provider for agentic mode |
|
3551b80…
|
noreply
|
384 |
from video_processor.providers.manager import ProviderManager |
|
3551b80…
|
noreply
|
385 |
pm = ProviderManager() |
|
3551b80…
|
noreply
|
386 |
engine = GraphQueryEngine.from_db_path(path, provider_manager=pm) |
|
3551b80…
|
noreply
|
387 |
``` |
|
3551b80…
|
noreply
|
388 |
|
|
3551b80…
|
noreply
|
389 |
### QueryResult |
|
3551b80…
|
noreply
|
390 |
|
|
3551b80…
|
noreply
|
391 |
All query methods return a `QueryResult` dataclass with multiple output formats: |
|
3551b80…
|
noreply
|
392 |
|
|
3551b80…
|
noreply
|
393 |
```python |
|
3551b80…
|
noreply
|
394 |
result = engine.stats() |
|
3551b80…
|
noreply
|
395 |
|
|
3551b80…
|
noreply
|
396 |
# Human-readable text |
|
3551b80…
|
noreply
|
397 |
print(result.to_text()) |
|
3551b80…
|
noreply
|
398 |
|
|
3551b80…
|
noreply
|
399 |
# JSON string |
|
3551b80…
|
noreply
|
400 |
print(result.to_json()) |
|
3551b80…
|
noreply
|
401 |
|
|
3551b80…
|
noreply
|
402 |
# Mermaid diagram (for graph results) |
|
3551b80…
|
noreply
|
403 |
result = engine.neighbors("Alice") |
|
3551b80…
|
noreply
|
404 |
print(result.to_mermaid()) |
|
3551b80…
|
noreply
|
405 |
``` |
|
3551b80…
|
noreply
|
406 |
|
|
3551b80…
|
noreply
|
407 |
The `QueryResult` contains: |
|
3551b80…
|
noreply
|
408 |
|
|
3551b80…
|
noreply
|
409 |
| Field | Type | Description | |
|
3551b80…
|
noreply
|
410 |
|---|---|---| |
|
3551b80…
|
noreply
|
411 |
| `data` | Any | The raw result data (dict, list, or scalar) | |
|
3551b80…
|
noreply
|
412 |
| `query_type` | str | `"filter"` for direct mode, `"agentic"` for LLM mode, `"sql"` for raw SQL | |
|
3551b80…
|
noreply
|
413 |
| `raw_query` | str | String representation of the executed query | |
|
3551b80…
|
noreply
|
414 |
| `explanation` | str | Human-readable explanation or LLM-synthesized answer | |
|
3551b80…
|
noreply
|
415 |
|
|
3551b80…
|
noreply
|
416 |
--- |
|
3551b80…
|
noreply
|
417 |
|
|
3551b80…
|
noreply
|
418 |
## The Self-Contained HTML Viewer |
|
3551b80…
|
noreply
|
419 |
|
|
3551b80…
|
noreply
|
420 |
PlanOpticon includes a zero-dependency HTML knowledge graph viewer at `knowledge-base/viewer.html`. This file is fully self-contained -- it inlines D3.js and requires no build step, no server, and no internet connection. |
|
3551b80…
|
noreply
|
421 |
|
|
3551b80…
|
noreply
|
422 |
To use it, open `viewer.html` in a browser. It will load and visualize a `knowledge_graph.json` file (place it in the same directory, or use the file picker in the viewer). |
|
3551b80…
|
noreply
|
423 |
|
|
3551b80…
|
noreply
|
424 |
The viewer provides: |
|
3551b80…
|
noreply
|
425 |
|
|
3551b80…
|
noreply
|
426 |
- Interactive force-directed graph layout |
|
3551b80…
|
noreply
|
427 |
- Zoom and pan navigation |
|
3551b80…
|
noreply
|
428 |
- Entity nodes colored by type |
|
3551b80…
|
noreply
|
429 |
- Relationship edges with labels |
|
3551b80…
|
noreply
|
430 |
- Click-to-focus on individual entities |
|
3551b80…
|
noreply
|
431 |
- Entity detail panel showing descriptions and connections |
|
3551b80…
|
noreply
|
432 |
|
|
3551b80…
|
noreply
|
433 |
This covers approximately 80% of graph exploration needs with zero infrastructure. |
|
3551b80…
|
noreply
|
434 |
|
|
3551b80…
|
noreply
|
435 |
--- |
|
3551b80…
|
noreply
|
436 |
|
|
3551b80…
|
noreply
|
437 |
## KG Management Commands |
|
3551b80…
|
noreply
|
438 |
|
|
3551b80…
|
noreply
|
439 |
The `planopticon kg` command group provides utilities for managing knowledge graph files. |
|
3551b80…
|
noreply
|
440 |
|
|
3551b80…
|
noreply
|
441 |
### kg convert |
|
3551b80…
|
noreply
|
442 |
|
|
3551b80…
|
noreply
|
443 |
Convert a knowledge graph between SQLite and JSON formats: |
|
3551b80…
|
noreply
|
444 |
|
|
3551b80…
|
noreply
|
445 |
```bash |
|
3551b80…
|
noreply
|
446 |
# SQLite to JSON |
|
3551b80…
|
noreply
|
447 |
planopticon kg convert results/knowledge_graph.db output.json |
|
3551b80…
|
noreply
|
448 |
|
|
3551b80…
|
noreply
|
449 |
# JSON to SQLite |
|
3551b80…
|
noreply
|
450 |
planopticon kg convert knowledge_graph.json knowledge_graph.db |
|
3551b80…
|
noreply
|
451 |
``` |
|
3551b80…
|
noreply
|
452 |
|
|
3551b80…
|
noreply
|
453 |
The output format is inferred from the destination file extension. Source and destination must be different formats. |
|
3551b80…
|
noreply
|
454 |
|
|
3551b80…
|
noreply
|
455 |
### kg sync |
|
3551b80…
|
noreply
|
456 |
|
|
3551b80…
|
noreply
|
457 |
Synchronize a `.db` and `.json` knowledge graph, updating the stale one: |
|
3551b80…
|
noreply
|
458 |
|
|
3551b80…
|
noreply
|
459 |
```bash |
|
3551b80…
|
noreply
|
460 |
# Auto-detect which is newer and sync |
|
3551b80…
|
noreply
|
461 |
planopticon kg sync results/knowledge_graph.db |
|
3551b80…
|
noreply
|
462 |
|
|
3551b80…
|
noreply
|
463 |
# Explicit JSON path |
|
3551b80…
|
noreply
|
464 |
planopticon kg sync knowledge_graph.db knowledge_graph.json |
|
3551b80…
|
noreply
|
465 |
|
|
3551b80…
|
noreply
|
466 |
# Force a specific direction |
|
3551b80…
|
noreply
|
467 |
planopticon kg sync knowledge_graph.db knowledge_graph.json --direction db-to-json |
|
3551b80…
|
noreply
|
468 |
planopticon kg sync knowledge_graph.db knowledge_graph.json --direction json-to-db |
|
3551b80…
|
noreply
|
469 |
``` |
|
3551b80…
|
noreply
|
470 |
|
|
3551b80…
|
noreply
|
471 |
If `JSON_PATH` is omitted, the `.json` path is derived from the `.db` path (same name, different extension). In `auto` mode (the default), the newer file is used as the source. |
|
3551b80…
|
noreply
|
472 |
|
|
3551b80…
|
noreply
|
473 |
### kg inspect |
|
3551b80…
|
noreply
|
474 |
|
|
3551b80…
|
noreply
|
475 |
Show summary statistics for a knowledge graph file: |
|
3551b80…
|
noreply
|
476 |
|
|
3551b80…
|
noreply
|
477 |
```bash |
|
3551b80…
|
noreply
|
478 |
planopticon kg inspect results/knowledge_graph.db |
|
3551b80…
|
noreply
|
479 |
``` |
|
3551b80…
|
noreply
|
480 |
|
|
3551b80…
|
noreply
|
481 |
Output: |
|
3551b80…
|
noreply
|
482 |
|
|
3551b80…
|
noreply
|
483 |
``` |
|
3551b80…
|
noreply
|
484 |
File: results/knowledge_graph.db |
|
3551b80…
|
noreply
|
485 |
Store: sqlite |
|
3551b80…
|
noreply
|
486 |
Entities: 42 |
|
3551b80…
|
noreply
|
487 |
Relationships: 87 |
|
3551b80…
|
noreply
|
488 |
Entity types: |
|
3551b80…
|
noreply
|
489 |
technology: 15 |
|
3551b80…
|
noreply
|
490 |
person: 12 |
|
3551b80…
|
noreply
|
491 |
concept: 10 |
|
3551b80…
|
noreply
|
492 |
organization: 5 |
|
3551b80…
|
noreply
|
493 |
``` |
|
3551b80…
|
noreply
|
494 |
|
|
3551b80…
|
noreply
|
495 |
Works with both `.db` and `.json` files. |
|
3551b80…
|
noreply
|
496 |
|
|
3551b80…
|
noreply
|
497 |
### kg classify |
|
3551b80…
|
noreply
|
498 |
|
|
3551b80…
|
noreply
|
499 |
Classify knowledge graph entities into planning taxonomy types: |
|
3551b80…
|
noreply
|
500 |
|
|
3551b80…
|
noreply
|
501 |
```bash |
|
3551b80…
|
noreply
|
502 |
# Heuristic + LLM classification |
|
3551b80…
|
noreply
|
503 |
planopticon kg classify results/knowledge_graph.db |
|
3551b80…
|
noreply
|
504 |
|
|
3551b80…
|
noreply
|
505 |
# Heuristic only (no API key needed) |
|
3551b80…
|
noreply
|
506 |
planopticon kg classify results/knowledge_graph.db -p none |
|
3551b80…
|
noreply
|
507 |
|
|
3551b80…
|
noreply
|
508 |
# JSON output |
|
3551b80…
|
noreply
|
509 |
planopticon kg classify results/knowledge_graph.db --format json |
|
3551b80…
|
noreply
|
510 |
``` |
|
3551b80…
|
noreply
|
511 |
|
|
3551b80…
|
noreply
|
512 |
Text output groups entities by planning type: |
|
3551b80…
|
noreply
|
513 |
|
|
3551b80…
|
noreply
|
514 |
``` |
|
3551b80…
|
noreply
|
515 |
GOALS (3) |
|
3551b80…
|
noreply
|
516 |
- Improve system reliability [high] |
|
3551b80…
|
noreply
|
517 |
Must achieve 99.9% uptime |
|
3551b80…
|
noreply
|
518 |
- Reduce deployment time [medium] |
|
3551b80…
|
noreply
|
519 |
Automate the deployment pipeline |
|
3551b80…
|
noreply
|
520 |
|
|
3551b80…
|
noreply
|
521 |
RISKS (2) |
|
3551b80…
|
noreply
|
522 |
- Data migration complexity [high] |
|
3551b80…
|
noreply
|
523 |
Legacy schema incompatibilities |
|
3551b80…
|
noreply
|
524 |
... |
|
3551b80…
|
noreply
|
525 |
|
|
3551b80…
|
noreply
|
526 |
TASKS (5) |
|
3551b80…
|
noreply
|
527 |
- Implement OAuth2 flow |
|
3551b80…
|
noreply
|
528 |
Set up authentication service |
|
3551b80…
|
noreply
|
529 |
... |
|
3551b80…
|
noreply
|
530 |
``` |
|
3551b80…
|
noreply
|
531 |
|
|
3551b80…
|
noreply
|
532 |
JSON output returns an array of `PlanningEntity` objects with `name`, `planning_type`, `priority`, `description`, and `source_entities` fields. |
|
3551b80…
|
noreply
|
533 |
|
|
3551b80…
|
noreply
|
534 |
### kg from-exchange |
|
3551b80…
|
noreply
|
535 |
|
|
3551b80…
|
noreply
|
536 |
Import a PlanOpticonExchange JSON file into a knowledge graph database: |
|
3551b80…
|
noreply
|
537 |
|
|
3551b80…
|
noreply
|
538 |
```bash |
|
3551b80…
|
noreply
|
539 |
# Import to default location (./knowledge_graph.db) |
|
3551b80…
|
noreply
|
540 |
planopticon kg from-exchange exchange.json |
|
3551b80…
|
noreply
|
541 |
|
|
3551b80…
|
noreply
|
542 |
# Import to a specific path |
|
3551b80…
|
noreply
|
543 |
planopticon kg from-exchange exchange.json -o project.db |
|
3551b80…
|
noreply
|
544 |
``` |
|
3551b80…
|
noreply
|
545 |
|
|
3551b80…
|
noreply
|
546 |
The PlanOpticonExchange format is a standardized interchange format that includes entities, relationships, and source records. |
|
3551b80…
|
noreply
|
547 |
|
|
3551b80…
|
noreply
|
548 |
--- |
|
3551b80…
|
noreply
|
549 |
|
|
3551b80…
|
noreply
|
550 |
## Output Formats |
|
3551b80…
|
noreply
|
551 |
|
|
3551b80…
|
noreply
|
552 |
Query results can be output in three formats: |
|
3551b80…
|
noreply
|
553 |
|
|
3551b80…
|
noreply
|
554 |
### Text (default) |
|
3551b80…
|
noreply
|
555 |
|
|
3551b80…
|
noreply
|
556 |
Human-readable format with entity types in brackets, relationship arrows, and indented details: |
|
3551b80…
|
noreply
|
557 |
|
|
3551b80…
|
noreply
|
558 |
``` |
|
3551b80…
|
noreply
|
559 |
Found 15 entities |
|
3551b80…
|
noreply
|
560 |
[technology] Python -- General-purpose programming language |
|
3551b80…
|
noreply
|
561 |
[person] Alice -- Lead engineer on the project |
|
3551b80…
|
noreply
|
562 |
[concept] Microservices -- Architectural pattern discussed |
|
3551b80…
|
noreply
|
563 |
``` |
|
3551b80…
|
noreply
|
564 |
|
|
3551b80…
|
noreply
|
565 |
### JSON |
|
3551b80…
|
noreply
|
566 |
|
|
3551b80…
|
noreply
|
567 |
Full structured output including query metadata: |
|
3551b80…
|
noreply
|
568 |
|
|
3551b80…
|
noreply
|
569 |
```bash |
|
3551b80…
|
noreply
|
570 |
planopticon query --format json stats |
|
3551b80…
|
noreply
|
571 |
``` |
|
3551b80…
|
noreply
|
572 |
|
|
3551b80…
|
noreply
|
573 |
```json |
|
3551b80…
|
noreply
|
574 |
{ |
|
3551b80…
|
noreply
|
575 |
"query_type": "filter", |
|
3551b80…
|
noreply
|
576 |
"raw_query": "stats()", |
|
3551b80…
|
noreply
|
577 |
"explanation": "Knowledge graph statistics", |
|
3551b80…
|
noreply
|
578 |
"data": { |
|
3551b80…
|
noreply
|
579 |
"entity_count": 42, |
|
3551b80…
|
noreply
|
580 |
"relationship_count": 87, |
|
3551b80…
|
noreply
|
581 |
"entity_types": { |
|
3551b80…
|
noreply
|
582 |
"technology": 15, |
|
3551b80…
|
noreply
|
583 |
"person": 12 |
|
3551b80…
|
noreply
|
584 |
} |
|
3551b80…
|
noreply
|
585 |
} |
|
3551b80…
|
noreply
|
586 |
} |
|
3551b80…
|
noreply
|
587 |
``` |
|
3551b80…
|
noreply
|
588 |
|
|
3551b80…
|
noreply
|
589 |
### Mermaid |
|
3551b80…
|
noreply
|
590 |
|
|
3551b80…
|
noreply
|
591 |
Graph results rendered as Mermaid diagram syntax, ready for embedding in markdown: |
|
3551b80…
|
noreply
|
592 |
|
|
3551b80…
|
noreply
|
593 |
```bash |
|
3551b80…
|
noreply
|
594 |
planopticon query --format mermaid "neighbors Alice" |
|
3551b80…
|
noreply
|
595 |
``` |
|
3551b80…
|
noreply
|
596 |
|
|
3551b80…
|
noreply
|
597 |
``` |
|
3551b80…
|
noreply
|
598 |
graph LR |
|
3551b80…
|
noreply
|
599 |
Alice["Alice"]:::person |
|
3551b80…
|
noreply
|
600 |
Python["Python"]:::technology |
|
3551b80…
|
noreply
|
601 |
Kubernetes["Kubernetes"]:::technology |
|
3551b80…
|
noreply
|
602 |
Alice -- "expert_in" --> Kubernetes |
|
3551b80…
|
noreply
|
603 |
Alice -- "works_with" --> Python |
|
3551b80…
|
noreply
|
604 |
classDef person fill:#f9d5e5,stroke:#333 |
|
3551b80…
|
noreply
|
605 |
classDef concept fill:#eeeeee,stroke:#333 |
|
3551b80…
|
noreply
|
606 |
classDef technology fill:#d5e5f9,stroke:#333 |
|
3551b80…
|
noreply
|
607 |
classDef organization fill:#f9e5d5,stroke:#333 |
|
3551b80…
|
noreply
|
608 |
``` |
|
3551b80…
|
noreply
|
609 |
|
|
3551b80…
|
noreply
|
610 |
The `KnowledgeGraph.generate_mermaid()` method also produces full-graph Mermaid diagrams, capped at the top 30 most-connected nodes by default. |
|
3551b80…
|
noreply
|
611 |
|
|
3551b80…
|
noreply
|
612 |
--- |
|
3551b80…
|
noreply
|
613 |
|
|
3551b80…
|
noreply
|
614 |
## Auto-Discovery |
|
3551b80…
|
noreply
|
615 |
|
|
3551b80…
|
noreply
|
616 |
PlanOpticon automatically locates knowledge graph files using the `find_nearest_graph()` function. The search order is: |
|
3551b80…
|
noreply
|
617 |
|
|
3551b80…
|
noreply
|
618 |
1. **Current directory** -- check for `knowledge_graph.db` and `knowledge_graph.json` |
|
3551b80…
|
noreply
|
619 |
2. **Common subdirectories** -- `results/`, `output/`, `knowledge-base/` |
|
3551b80…
|
noreply
|
620 |
3. **Recursive downward walk** -- up to 4 levels deep, skipping hidden directories |
|
3551b80…
|
noreply
|
621 |
4. **Parent directory walk** -- upward through the directory tree, checking each level and its common subdirectories |
|
3551b80…
|
noreply
|
622 |
|
|
3551b80…
|
noreply
|
623 |
Within each search phase, `.db` files are preferred over `.json` files. Results are sorted by proximity (closest first). |
|
3551b80…
|
noreply
|
624 |
|
|
3551b80…
|
noreply
|
625 |
```python |
|
3551b80…
|
noreply
|
626 |
from video_processor.integrators.graph_discovery import ( |
|
3551b80…
|
noreply
|
627 |
find_nearest_graph, |
|
3551b80…
|
noreply
|
628 |
find_knowledge_graphs, |
|
3551b80…
|
noreply
|
629 |
describe_graph, |
|
3551b80…
|
noreply
|
630 |
) |
|
3551b80…
|
noreply
|
631 |
|
|
3551b80…
|
noreply
|
632 |
# Find the single closest knowledge graph |
|
3551b80…
|
noreply
|
633 |
path = find_nearest_graph() |
|
3551b80…
|
noreply
|
634 |
|
|
3551b80…
|
noreply
|
635 |
# Find all knowledge graphs, sorted by proximity |
|
3551b80…
|
noreply
|
636 |
paths = find_knowledge_graphs() |
|
3551b80…
|
noreply
|
637 |
|
|
3551b80…
|
noreply
|
638 |
# Find graphs starting from a specific directory |
|
3551b80…
|
noreply
|
639 |
paths = find_knowledge_graphs(start_dir="/path/to/project") |
|
3551b80…
|
noreply
|
640 |
|
|
3551b80…
|
noreply
|
641 |
# Disable upward walking |
|
3551b80…
|
noreply
|
642 |
paths = find_knowledge_graphs(walk_up=False) |
|
3551b80…
|
noreply
|
643 |
|
|
3551b80…
|
noreply
|
644 |
# Get summary stats without loading the full graph |
|
3551b80…
|
noreply
|
645 |
info = describe_graph(path) |
|
3551b80…
|
noreply
|
646 |
# {"entity_count": 42, "relationship_count": 87, |
|
3551b80…
|
noreply
|
647 |
# "entity_types": {...}, "store_type": "sqlite"} |
|
3551b80…
|
noreply
|
648 |
``` |
|
3551b80…
|
noreply
|
649 |
|
|
3551b80…
|
noreply
|
650 |
Auto-discovery is used by the Companion REPL, the `planopticon query` command, and the planning agent when no explicit `--kb` path is provided. |