Skip to content

Commit 9191171

Browse files
committed
Merge branch 'main' of github.com:microsoft/agent-lightning into codex/add-tutorial-for-launching-workers
2 parents 784851b + c16b3a2 commit 9191171

File tree

7 files changed

+3124
-1328
lines changed

7 files changed

+3124
-1328
lines changed

.github/workflows/docs.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ on:
88
- 'v*'
99
workflow_dispatch:
1010

11+
concurrency:
12+
group: docs-deploy
13+
cancel-in-progress: false
14+
1115
permissions:
1216
contents: write
1317
pages: write

agentlightning/trainer/trainer.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ class Trainer(TrainerLegacy):
114114
or a dictionary with the initialization parameters for the exporter.
115115
Deprecated. Use [`adapter`][agentlightning.Trainer.adapter] instead."""
116116

117+
port: Optional[int]
118+
"""Port forwarded to [`ClientServerExecutionStrategy`][agentlightning.ClientServerExecutionStrategy]."""
119+
117120
def __init__(
118121
self,
119122
*,
@@ -126,6 +129,7 @@ def __init__(
126129
store: ComponentSpec[LightningStore] = None,
127130
runner: ComponentSpec[Runner[Any]] = None,
128131
strategy: ComponentSpec[ExecutionStrategy] = None,
132+
port: Optional[int] = None,
129133
algorithm: ComponentSpec[Algorithm] = None,
130134
llm_proxy: ComponentSpec[LLMProxy] = None,
131135
n_workers: Optional[int] = None,
@@ -139,6 +143,10 @@ def __init__(
139143
Each keyword accepts either a concrete instance, a class, a callable factory, a
140144
registry string, or a lightweight configuration dictionary (see
141145
[`build_component()`][agentlightning.trainer.init_utils.build_component]).
146+
147+
When ``port`` is provided it is forwarded to
148+
[`ClientServerExecutionStrategy`][agentlightning.ClientServerExecutionStrategy]
149+
instances constructed (or supplied) for the trainer.
142150
"""
143151
# Do not call super().__init__() here.
144152
# super().__init__() will call TrainerLegacy's initialization, which is not intended.
@@ -209,7 +217,13 @@ def __init__(
209217
self.store = self._make_store(store)
210218
self.runner = self._make_runner(runner)
211219

212-
self.strategy = self._make_strategy(strategy, n_runners=self.n_runners)
220+
self.port = port
221+
222+
self.strategy = self._make_strategy(
223+
strategy,
224+
n_runners=self.n_runners,
225+
port=port,
226+
)
213227
if hasattr(self.strategy, "n_runners"):
214228
strategy_runners = getattr(self.strategy, "n_runners")
215229
if isinstance(strategy_runners, int) and strategy_runners > 0:
@@ -284,13 +298,20 @@ def _make_strategy(
284298
strategy: ComponentSpec[ExecutionStrategy],
285299
*,
286300
n_runners: int,
301+
port: Optional[int] = None,
287302
) -> ExecutionStrategy:
288303
"""Resolve the execution strategy and seed defaults such as `n_runners`."""
289304
if isinstance(strategy, ExecutionStrategy):
305+
if port is not None and isinstance(strategy, ClientServerExecutionStrategy):
306+
strategy.server_port = port
290307
return strategy
291308
optional_defaults: Dict[str, Callable[[], Any]] = {"n_runners": lambda: n_runners}
309+
if port is not None:
310+
optional_defaults["server_port"] = lambda: port
292311

293312
def default_factory() -> ExecutionStrategy:
313+
if port is not None:
314+
return ClientServerExecutionStrategy(n_runners=n_runners, server_port=port)
294315
return ClientServerExecutionStrategy(n_runners=n_runners)
295316

296317
return build_component(

agentlightning/types/tracer.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from opentelemetry.sdk.trace import ReadableSpan
1515
from opentelemetry.sdk.trace.id_generator import RandomIdGenerator
1616
from opentelemetry.trace.status import Status as OtelStatus
17-
from pydantic import BaseModel
17+
from pydantic import BaseModel, ConfigDict
1818

1919
__all__ = [
2020
"AttributeValue",
@@ -95,8 +95,7 @@ class SpanContext(BaseModel):
9595
trace_state: TraceState
9696
"""Mapping from trace state key to its value."""
9797

98-
class Config:
99-
allow_extra = True
98+
model_config = ConfigDict(extra="allow")
10099

101100
@classmethod
102101
def from_opentelemetry(cls, src: trace_api.SpanContext) -> "SpanContext":
@@ -119,8 +118,7 @@ class TraceStatus(BaseModel):
119118
description: Optional[str] = None
120119
"""The description of the span. Same as OpenTelemetry `Status.description` type."""
121120

122-
class Config:
123-
allow_extra = True
121+
model_config = ConfigDict(extra="allow")
124122

125123
@classmethod
126124
def from_opentelemetry(cls, src: OtelStatus) -> "TraceStatus":
@@ -143,8 +141,7 @@ class Event(BaseModel):
143141
timestamp: Optional[float] = None
144142
"""The timestamp of the event. Same as OpenTelemetry `Event.timestamp` type."""
145143

146-
class Config:
147-
allow_extra = True
144+
model_config = ConfigDict(extra="allow")
148145

149146
@classmethod
150147
def from_opentelemetry(cls, src: OtelEvent) -> "Event":
@@ -166,8 +163,7 @@ class Link(BaseModel):
166163
attributes: Optional[Attributes] = None
167164
"""Optional attributes."""
168165

169-
class Config:
170-
allow_extra = True
166+
model_config = ConfigDict(extra="allow")
171167

172168
@classmethod
173169
def from_opentelemetry(cls, src: trace_api.Link) -> "Link":
@@ -214,8 +210,7 @@ class Span(BaseModel):
214210
stable even as upstream OpenTelemetry types evolve.
215211
"""
216212

217-
class Config:
218-
allow_extra = True # allow extra fields if needed
213+
model_config = ConfigDict(extra="allow")
219214

220215
rollout_id: str
221216
"""The rollout which this span belongs to."""

docs/algorithm-zoo/verl.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pip install agentlightning[verl]
2222

2323
!!! note "Notes for Readers"
2424

25-
[VERL][agentlightning.algorithm.verl.VERL] in this article refers to a wrapper, provided by Agent-lightning, of the VERL framework. It's a subclass of [agentlightning.Algorithm][]. To differentiate it from the VERL framework, all references to the VERL framework shall use the term "VERL framework", and all references to the Agent-lightning wrapper shall be highlighted with a link.
25+
[VERL][agentlightning.algorithm.verl.VERL] in this article refers to a wrapper, provided by Agent-lightning, of the [VERL framework](https://github.com/volcengine/verl). It's a subclass of [agentlightning.Algorithm][]. To differentiate it from the VERL framework, all references to the VERL framework shall use the term "VERL framework", and all references to the Agent-lightning wrapper shall be highlighted with a link.
2626

2727
## Resources
2828

pyproject.toml

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ experiment = [
6363
]
6464

6565
core-legacy = [
66-
"agentops<=0.4.18"
66+
"agentops<=0.4.18",
67+
"openai<2.0.0",
6768
]
6869
core-stable = [
69-
"agentops>=0.4.21"
70+
"agentops>=0.4.21",
71+
"openai>=2.0.0",
7072
]
7173

7274
# For PyTorch.
@@ -123,8 +125,8 @@ trl = [
123125
# Only work with PyTorch 2.8.0+.
124126
{include-group = "torch-stable"},
125127
# https://github.com/unslothai/unsloth/issues/3451
126-
"unsloth<=2025.10.1",
127-
"unsloth_zoo<=2025.10.1",
128+
"unsloth>=2025.10.1,!=2025.10.2,!=2025.10.3,!=2025.10.4,!=2025.10.5,!=2025.10.6,!=2025.10.7,!=2025.10.8",
129+
"unsloth_zoo>=2025.10.1,!=2025.10.2,!=2025.10.3,!=2025.10.4,!=2025.10.5,!=2025.10.6,!=2025.10.7,!=2025.10.8",
128130
"bitsandbytes",
129131
"peft",
130132
"datasets",
@@ -134,6 +136,13 @@ trl = [
134136
"vllm",
135137
]
136138

139+
# For Tinker integration.
140+
tinker = [
141+
{include-group = "torch-stable"},
142+
"tinker>=0.2.2",
143+
"tinker_cookbook",
144+
]
145+
137146
# Agent-related dependencies.
138147
autogen = [
139148
"autogen-agentchat",
@@ -160,6 +169,9 @@ sql = [
160169
"sqlparse",
161170
"nltk",
162171
]
172+
crewai = [
173+
"crewai[tools]>=1.2.0",
174+
]
163175

164176
# Summarize into large installable groups.
165177
agents = [
@@ -168,9 +180,11 @@ agents = [
168180
{include-group = "langchain"},
169181
{include-group = "sql"},
170182
{include-group = "anthropic"},
183+
{include-group = "crewai"},
171184
]
172185

173186
[tool.uv]
187+
required-version = ">=0.9.5"
174188
conflicts = [
175189
[
176190
{ group = "core-legacy" },
@@ -189,15 +203,25 @@ environments = [
189203
"sys_platform == 'linux'",
190204
]
191205
dependency-metadata = [
206+
# Patch the dependencies of instructor to unpin "openai".
207+
# This is a workaround for https://github.com/567-labs/instructor/issues/1852
208+
{ name = "instructor", version = "1.11.3", requires-dist = ["openai", "pydantic", "docstring-parser", "typer", "rich", "aiohttp", "tenacity", "pydantic-core", "jiter", "jinja2", "requests", "diskcache"] },
209+
]
210+
211+
override-dependencies = [
212+
# A conflict between the dependency of litellm[proxy] and crewai[tools]
213+
"mcp>=1.19.0",
214+
"uvicorn>=0.38.0",
192215
# Conflicts between packaging dependency of pyvers (dependency of tensordict) and agentops.
193-
{ name = "pyvers", version = "0.1.0", requires-dist = ["packaging>=24.0"] },
216+
"packaging>=24.0",
194217
]
195218

196219
[tool.uv.sources]
197220
torch = [
198221
{ index = "pytorch-cu128", group = "torch-cu128" },
199222
{ index = "pytorch-cpu", group = "torch-cpu" },
200223
]
224+
tinker_cookbook = { git = "https://github.com/thinking-machines-lab/tinker-cookbook", rev = "72ba5e6a1f52c0887e2674615e318ce21a39cc2a" }
201225

202226
[[tool.uv.index]]
203227
name = "pypi"
@@ -216,6 +240,9 @@ flash-attn = [
216240
{ requirement = "torch", match-runtime = true },
217241
]
218242

243+
[tool.uv.dependency-groups]
244+
tinker = {requires-python = ">=3.11"}
245+
219246
[build-system]
220247
requires = ["hatchling"]
221248
build-backend = "hatchling.build"

tests/trainer/test_trainer_init.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,46 @@ def test_trainer_with_client_server_strategy_dict() -> None:
7777
assert trainer.strategy.server_port == 9999
7878

7979

80+
def test_trainer_port_forwarded_to_client_server_strategy() -> None:
81+
"""Test that the top-level port argument configures the client-server strategy."""
82+
trainer = agl.Trainer(
83+
algorithm=agl.Baseline(),
84+
n_runners=4,
85+
port=8081,
86+
)
87+
88+
assert isinstance(trainer.strategy, agl.ClientServerExecutionStrategy)
89+
assert trainer.strategy.server_port == 8081
90+
91+
92+
def test_trainer_port_ignored_for_non_client_server_strategy() -> None:
93+
"""Test that port has no effect when using a non client-server strategy."""
94+
trainer = agl.Trainer(
95+
algorithm=agl.Baseline(),
96+
n_runners=1,
97+
port=8082,
98+
strategy="shm",
99+
)
100+
101+
assert isinstance(trainer.strategy, agl.SharedMemoryExecutionStrategy)
102+
assert not hasattr(trainer.strategy, "server_port")
103+
104+
105+
def test_trainer_port_overrides_existing_client_server_strategy() -> None:
106+
"""Test that provided port overrides an initialized client-server strategy."""
107+
strategy = agl.ClientServerExecutionStrategy(server_port=9000)
108+
109+
trainer = agl.Trainer(
110+
algorithm=agl.Baseline(),
111+
n_runners=1,
112+
strategy=strategy,
113+
port=9100,
114+
)
115+
116+
assert trainer.strategy is strategy
117+
assert trainer.strategy.server_port == 9100 # type: ignore
118+
119+
80120
def test_trainer_with_env_vars_for_execution_strategy(monkeypatch: pytest.MonkeyPatch) -> None:
81121
"""Test that execution strategy supports environment variables to override values."""
82122
algorithm = agl.Baseline()

0 commit comments

Comments
 (0)