PlanOpticon

fix(diagram): handle Ollama llava returning dicts for relationships llava:latest returns relationship objects like {"source": "A", "destination": "B"} instead of strings like "A -> B: relationship". This caused Pydantic validation to fail on DiagramResult, crashing the entire pipeline. - Normalize relationship entries: convert dicts to "src -> dst: label" strings - Wrap DiagramResult construction in try/except, fall back to screengrab on failure

lmata 2026-02-17 05:43 trunk
Commit 54cb35343d57909d075d7d8be8925e4c87d3265b6b234647f2a67ca2f34f0806
--- video_processor/analyzers/diagram_analyzer.py
+++ video_processor/analyzers/diagram_analyzer.py
@@ -194,21 +194,47 @@
194194
try:
195195
diagram_type = DiagramType(dtype)
196196
except ValueError:
197197
diagram_type = DiagramType.unknown
198198
199
- dr = DiagramResult(
200
- frame_index=i,
201
- diagram_type=diagram_type,
202
- confidence=confidence,
203
- description=analysis.get("description"),
204
- text_content=analysis.get("text_content"),
205
- elements=analysis.get("elements") or [],
206
- relationships=analysis.get("relationships") or [],
207
- mermaid=analysis.get("mermaid"),
208
- chart_data=analysis.get("chart_data"),
209
- )
199
+ # Normalize relationships: llava sometimes returns dicts instead of strings
200
+ raw_rels = analysis.get("relationships") or []
201
+ relationships = []
202
+ for rel in raw_rels:
203
+ if isinstance(rel, str):
204
+ relationships.append(rel)
205
+ elif isinstance(rel, dict):
206
+ src = rel.get("source", rel.get("from", "?"))
207
+ dst = rel.get("destination", rel.get("to", "?"))
208
+ label = rel.get("label", rel.get("relationship", ""))
209
+ relationships.append(
210
+ f"{src} -> {dst}: {label}" if label else f"{src} -> {dst}"
211
+ )
212
+ else:
213
+ relationships.append(str(rel))
214
+
215
+ try:
216
+ dr = DiagramResult(
217
+ frame_index=i,
218
+ diagram_type=diagram_type,
219
+ confidence=confidence,
220
+ description=analysis.get("description"),
221
+ text_content=analysis.get("text_content"),
222
+ elements=analysis.get("elements") or [],
223
+ relationships=relationships,
224
+ mermaid=analysis.get("mermaid"),
225
+ chart_data=analysis.get("chart_data"),
226
+ )
227
+ except Exception as e:
228
+ logger.warning(
229
+ f"DiagramResult validation failed for frame {i}: {e}, "
230
+ "falling back to screengrab"
231
+ )
232
+ capture = self._save_screengrab(fp, i, capture_idx, captures_dir, confidence)
233
+ captures.append(capture)
234
+ capture_idx += 1
235
+ continue
210236
211237
# Save outputs (story 3.4)
212238
if diagrams_dir:
213239
diagrams_dir.mkdir(parents=True, exist_ok=True)
214240
prefix = f"diagram_{diagram_idx}"
215241
--- video_processor/analyzers/diagram_analyzer.py
+++ video_processor/analyzers/diagram_analyzer.py
@@ -194,21 +194,47 @@
194 try:
195 diagram_type = DiagramType(dtype)
196 except ValueError:
197 diagram_type = DiagramType.unknown
198
199 dr = DiagramResult(
200 frame_index=i,
201 diagram_type=diagram_type,
202 confidence=confidence,
203 description=analysis.get("description"),
204 text_content=analysis.get("text_content"),
205 elements=analysis.get("elements") or [],
206 relationships=analysis.get("relationships") or [],
207 mermaid=analysis.get("mermaid"),
208 chart_data=analysis.get("chart_data"),
209 )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
211 # Save outputs (story 3.4)
212 if diagrams_dir:
213 diagrams_dir.mkdir(parents=True, exist_ok=True)
214 prefix = f"diagram_{diagram_idx}"
215
--- video_processor/analyzers/diagram_analyzer.py
+++ video_processor/analyzers/diagram_analyzer.py
@@ -194,21 +194,47 @@
194 try:
195 diagram_type = DiagramType(dtype)
196 except ValueError:
197 diagram_type = DiagramType.unknown
198
199 # Normalize relationships: llava sometimes returns dicts instead of strings
200 raw_rels = analysis.get("relationships") or []
201 relationships = []
202 for rel in raw_rels:
203 if isinstance(rel, str):
204 relationships.append(rel)
205 elif isinstance(rel, dict):
206 src = rel.get("source", rel.get("from", "?"))
207 dst = rel.get("destination", rel.get("to", "?"))
208 label = rel.get("label", rel.get("relationship", ""))
209 relationships.append(
210 f"{src} -> {dst}: {label}" if label else f"{src} -> {dst}"
211 )
212 else:
213 relationships.append(str(rel))
214
215 try:
216 dr = DiagramResult(
217 frame_index=i,
218 diagram_type=diagram_type,
219 confidence=confidence,
220 description=analysis.get("description"),
221 text_content=analysis.get("text_content"),
222 elements=analysis.get("elements") or [],
223 relationships=relationships,
224 mermaid=analysis.get("mermaid"),
225 chart_data=analysis.get("chart_data"),
226 )
227 except Exception as e:
228 logger.warning(
229 f"DiagramResult validation failed for frame {i}: {e}, "
230 "falling back to screengrab"
231 )
232 capture = self._save_screengrab(fp, i, capture_idx, captures_dir, confidence)
233 captures.append(capture)
234 capture_idx += 1
235 continue
236
237 # Save outputs (story 3.4)
238 if diagrams_dir:
239 diagrams_dir.mkdir(parents=True, exist_ok=True)
240 prefix = f"diagram_{diagram_idx}"
241

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button