Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
192949c
checkpoint of WIP JSON OTEL demo
doxav Oct 3, 2025
2f1794b
working OTEL/LANGGRAPH demo
doxav Oct 5, 2025
bc0b304
converted demo JSON/OpenTelemetry to LangGraph
doxav Oct 5, 2025
e81ad34
checkpoint
doxav Oct 6, 2025
a71e1ed
OTEL/JSON/LANGGRAPH demo: add a mechanism to ensure multiple optimiza…
doxav Oct 6, 2025
53871aa
ADDED batchify for handling the multiple feedback in a batch + ADDED …
doxav Nov 6, 2025
87d3c67
working code optimization - TODO: clean, simplify the code
doxav Nov 7, 2025
da80055
fixed code optimization
doxav Nov 20, 2025
d88a779
ADD synthtizer prompt in optim score > High score
doxav Nov 20, 2025
d03fec5
TEST removing span/OTEL from optimized code
doxav Nov 20, 2025
1692a89
fixed and updated LangGraph/Otel demo README
doxav Nov 21, 2025
1c75117
restore
doxav Nov 25, 2025
779db55
ADD demo and tests for native LangGraph integration with OTEL tracing
doxav Dec 11, 2025
23a377c
ADD refactor run_graph_with_otel to support custom evaluation functio…
doxav Dec 12, 2025
d19ba70
ADD implement run_benchmark function to compare different feedback mode
doxav Dec 12, 2025
22d1064
ADD M0 technical plan, architecture docs, and prototype API validation
JZOMVI Feb 6, 2026
30a89c8
Fix Colab badge URL: replace placeholders with actual repo/branch path
JZOMVI Feb 6, 2026
6760695
ADD Colab Secrets key retrieval and Google Drive auto-save to notebook
JZOMVI Feb 6, 2026
c85baf8
Update T1 tech plan: notebooks + acceptance alignment + fixed opto/tr…
doxav Feb 8, 2026
c8dfc04
ADD M1 core: instrument_graph + optimize_graph + E2E pipeline + notebook
JZOMVI Feb 12, 2026
2f0d53d
FIX: address all feedback issues (A1-F13)
JZOMVI Feb 12, 2026
1e218e0
REFACTOR: remove all hardcoded/example-specific defaults from library…
mjehanzaib999 Feb 13, 2026
bd4f556
fix(optimization): correct best_updates tracking to reflect actual be…
mjehanzaib999 Feb 16, 2026
1ec38cc
fix(optimization): fall back to graph.output_key in optimize_graph()
mjehanzaib999 Feb 16, 2026
55f4dda
fix(instrumentation): wire enable_code_optimization to TracingLLM
mjehanzaib999 Feb 16, 2026
084cbf8
fix(otel): prevent dangling TGJ parents and record errors on child spans
mjehanzaib999 Feb 16, 2026
856b05f
fix(notebook): replace brittle name heuristics with attribute-based t…
mjehanzaib999 Feb 17, 2026
c39bed8
Merge branch 'experimental' of https://github.com/AgentOpt/OpenTrace …
mjehanzaib999 Feb 19, 2026
3c772b9
Merge branch 'experimental' of https://github.com/AgentOpt/OpenTrace …
mjehanzaib999 Feb 19, 2026
1abefdc
fix: address PR feedback round 2 — multi-node notebook + error.messag…
mjehanzaib999 Feb 19, 2026
8978ff7
fix: replace custom OpenRouterLLM with Trace LiteLLM, use real OptoPr…
mjehanzaib999 Feb 20, 2026
cb2eede
fix: update retired OpenRouter model to llama-3.3-70b-instruct:free
mjehanzaib999 Feb 20, 2026
0f09eed
fix: use OPENAI_BASE_URL env var for OpenRouter routing
mjehanzaib999 Feb 20, 2026
6fb3c92
fix: add openai/ prefix for litellm OpenRouter routing
mjehanzaib999 Feb 20, 2026
73f48bf
fix: use openai package directly for OpenRouter, add smoke test
mjehanzaib999 Feb 20, 2026
fd2da29
fix: switch to Qwen3 model, use built-in eval_fn for live optimization
mjehanzaib999 Feb 20, 2026
82d0c31
fix: use paid meta-llama/llama-3.3-70b-instruct to avoid free-tier ra…
mjehanzaib999 Feb 20, 2026
306b306
fix: resolve ParameterNode-keyed updates in live optimization
mjehanzaib999 Feb 23, 2026
a373dad
fix: per-query optimizer step to avoid feedback aggregation assertion
mjehanzaib999 Feb 23, 2026
fea60a4
fix: use batchify for multi-query backward pass instead of per-query …
mjehanzaib999 Feb 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# OpenRouter Configuration
# Copy this file to .env and fill in your values
# Get your API key from: https://openrouter.ai/keys

OPENROUTER_API_KEY=sk-or-v1-your-key-here
OPENROUTER_MODEL=meta-llama/llama-3.1-8b-instruct:free
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
USE_STUB_LLM=false
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,6 @@ OAI_CONFIG_LIST
*.gv.pdf

# jupyter book API output
docs/api/*
docs/api/*

uv.lock
2,072 changes: 2,072 additions & 0 deletions 01_m1_instrument_and_optimize(5)(1).ipynb

Large diffs are not rendered by default.

1,618 changes: 1,618 additions & 0 deletions OpenTrace_LangGraph_BBEH_boolean_expressions_PAL_curriculum_clean(3).ipynb

Large diffs are not rendered by default.

164 changes: 164 additions & 0 deletions T1_PR_M1_latest_fix.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
diff --git a/opto/trace/io/bindings.py b/opto/trace/io/bindings.py
index 5f3e0bf..a7e7e4a 100644
--- a/opto/trace/io/bindings.py
+++ b/opto/trace/io/bindings.py
@@ -1,10 +1,12 @@
from __future__ import annotations

import logging
+import re
from dataclasses import dataclass
from typing import Any, Callable, Dict, Literal

logger = logging.getLogger(__name__)
@@
def apply_updates(
- updates: Dict[str, Any],
+ updates: Dict[Any, Any],
bindings: Dict[str, Binding],
*,
strict: bool = True,
-) -> None:
+) -> Dict[str, Any]:
@@
- for key, value in updates.items():
- binding = bindings.get(key)
+ def _normalize_key(k: Any) -> str:
+ if isinstance(k, str):
+ s = k
+ else:
+ s = (
+ getattr(k, "name", None)
+ or getattr(k, "_name", None)
+ or getattr(k, "py_name", None)
+ or str(k)
+ )
+ s = str(s).strip()
+ if s.startswith("param."):
+ s = s[len("param."):]
+ s = s.split(":")[0].split("/")[-1]
+ if s not in bindings:
+ s2 = re.sub(r"\d+$", "", s)
+ if s2 in bindings:
+ s = s2
+ return s
+
+ applied: Dict[str, Any] = {}
+ for raw_key, value in updates.items():
+ key = _normalize_key(raw_key)
+ binding = bindings.get(key)
if binding is None:
if strict:
raise KeyError(
- f"apply_updates: no binding for key {key!r}. "
+ f"apply_updates: no binding for key {key!r} (from {raw_key!r}). "
f"Available bindings: {sorted(bindings.keys())}"
)
- logger.debug("apply_updates: skipping unknown key %r (strict=False)", key)
+ logger.debug("apply_updates: skipping unknown key %r (from %r)", key, raw_key)
continue
try:
binding.set(value)
+ applied[key] = value
logger.debug("apply_updates: set %r (kind=%s)", key, binding.kind)
except Exception:
logger.exception("apply_updates: failed to set %r", key)
+ if strict:
+ raise
+ return applied

diff --git a/opto/trace/io/tgj_ingest.py b/opto/trace/io/tgj_ingest.py
index 95d3c70..c651d1b 100644
--- a/opto/trace/io/tgj_ingest.py
+++ b/opto/trace/io/tgj_ingest.py
@@ -1,6 +1,7 @@
from __future__ import annotations

from dataclasses import dataclass
+from typing import Optional
from typing import Any, Dict, List, Tuple
@@
-def ingest_tgj(doc: Dict[str,Any], port_index: Optional[Dict[str,Node]] = None) -> Dict[str,Node]:
+def ingest_tgj(
+ doc: Dict[str,Any],
+ port_index: Optional[Dict[str,Node]] = None,
+ *,
+ param_cache: Optional[Dict[str,"ParameterNode"]] = None,
+) -> Dict[str,Node]:
@@
if k == "parameter":
- n = ParameterNode(
- rec.get("value"),
- name=nm,
- trainable=bool(rec.get("trainable", True)),
- description=rec.get("description", "[Parameter]")
- )
+ n = param_cache.get(nid) if param_cache is not None else None
+ if n is None:
+ n = ParameterNode(
+ rec.get("value"),
+ name=nm,
+ trainable=bool(rec.get("trainable", True)),
+ description=rec.get("description", "[Parameter]"),
+ )
+ if param_cache is not None:
+ param_cache[nid] = n
+ else:
+ try:
+ n._data = rec.get("value")
+ except Exception:
+ pass
+ try:
+ n.trainable = bool(rec.get("trainable", True))
+ except Exception:
+ pass
nodes[nid] = n
nodes[nm] = n

diff --git a/opto/trace/io/optimization.py b/opto/trace/io/optimization.py
index 271e2b1..a9f0d44 100644
--- a/opto/trace/io/optimization.py
+++ b/opto/trace/io/optimization.py
@@ -210,6 +210,7 @@ def optimize_graph(
eval_fn = eval_fn or _default_eval_fn

+ graph.session.flush_otlp(clear=True)
score_history: List[float] = []
@@
best_updates: Dict[str, Any] = {}
last_applied_updates: Dict[str, Any] = {}

+ param_cache: Dict[str, Any] = {}
@@
- nodes = _ingest_tgj(doc)
+ nodes = _ingest_tgj(doc, param_cache=param_cache)
@@
if _optimizer is not None and all_output_nodes:
try:
_optimizer.zero_feedback()
- _optimizer.backward(output_node, feedback_text)
+ for output_node, run_for_output in all_output_nodes:
+ feedback_text = run_for_output.feedback or (
+ f"Score: {run_for_output.score}"
+ if run_for_output.score is not None
+ else "No feedback"
+ )
+ _optimizer.backward(output_node, feedback_text)
raw_updates = _optimizer.step()
if isinstance(raw_updates, dict):
updates.update(raw_updates)
except Exception as exc:
logger.warning(
"Optimizer step failed: %s", exc, exc_info=True
)
@@
if updates and apply_updates_flag:
try:
- apply_updates(updates, effective_bindings, strict=False)
- last_applied_updates = dict(updates)
- logger.info("Applied updates: %s", sorted(updates.keys()))
+ applied = apply_updates(updates, effective_bindings, strict=False)
+ last_applied_updates = dict(applied)
+ logger.info("Applied updates: %s", sorted(applied.keys()))
except Exception as exc:
logger.warning("apply_updates failed: %s", exc, exc_info=True)
Loading