Skip to content

Commit e7cb0de

Browse files
fix(examples): hello-world base_url default and observer trace
Two bugs surfaced during live validation against OpenAI: - The default LLM_BASE_URL was https://api.openai.com/v1, but our OpenAIProvider's wire path posts to /v1/chat/completions itself. httpx URL join produced https://api.openai.com/v1/v1/chat/completions → 404. Convention is base_url = host root; impl adds /v1. Default now matches; doc-string + README comment make it explicit. - The observer trace fired on the OpenAIProvider LLM-span event (sentinel namespace, post_state=None) and crashed accessing .sources. Added a post_state is not None guard.
1 parent 2d39a56 commit e7cb0de

2 files changed

Lines changed: 10 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class PipelineState(State):
8585

8686

8787
provider = OpenAIProvider(
88-
base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1"),
88+
base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com"), # host root; impl adds /v1
8989
model=os.environ.get("LLM_MODEL", "gpt-4o-mini"),
9090
api_key=os.environ.get("LLM_API_KEY"),
9191
)
@@ -113,7 +113,7 @@ def route(state: PipelineState) -> str:
113113

114114

115115
async def trace(event: NodeEvent) -> None:
116-
if event.phase == "completed" and event.error is None:
116+
if event.phase == "completed" and event.error is None and event.post_state is not None:
117117
print(f"{event.node_name}: sources={event.post_state.sources}")
118118

119119

examples/00-hello-world/main.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
1515
**Configuration** (env vars; OpenAI defaults shown):
1616
17-
- ``LLM_BASE_URL`` — defaults to ``https://api.openai.com/v1``.
17+
- ``LLM_BASE_URL`` — defaults to ``https://api.openai.com``. **Host
18+
root only** — the impl adds ``/v1/chat/completions`` and
19+
``/v1/models`` itself, so do NOT include ``/v1`` in this value.
1820
- ``LLM_MODEL`` — defaults to ``gpt-4o-mini``.
1921
- ``LLM_API_KEY`` — required (your OpenAI API key, or empty for
2022
local servers that don't authenticate).
@@ -67,7 +69,7 @@ class PipelineState(State):
6769

6870

6971
_provider = OpenAIProvider(
70-
base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1"),
72+
base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com"),
7173
model=os.environ.get("LLM_MODEL", "gpt-4o-mini"),
7274
api_key=os.environ.get("LLM_API_KEY"),
7375
)
@@ -103,7 +105,10 @@ def route(state: PipelineState) -> str:
103105

104106

105107
async def trace(event: NodeEvent) -> None:
106-
if event.phase == "completed" and event.error is None:
108+
# OpenAIProvider emits NodeEvent-shaped events for LLM-span
109+
# tracking under a sentinel namespace; those have post_state=None.
110+
# Filter to events that carry a state snapshot before reading it.
111+
if event.phase == "completed" and event.error is None and event.post_state is not None:
107112
print(f"{event.node_name}: sources={event.post_state.sources}")
108113

109114

0 commit comments

Comments
 (0)