Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 21 additions & 14 deletions responses_api_agents/browsecomp_agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import traceback
from datetime import datetime
from pathlib import Path
from typing import List, Optional
from typing import List, Mapping, Optional, Tuple

from fastapi import Request, Response
from pydantic import ConfigDict, ValidationError
Expand Down Expand Up @@ -126,6 +126,17 @@ async def responses(
response: Response,
body: NeMoGymResponseCreateParamsNonStreaming = Body(),
) -> NeMoGymResponse:
result, set_cookies = await self._responses(body, request.cookies)
for k, v in set_cookies.items():
response.set_cookie(k, v)
return result

async def _responses(
self,
body: NeMoGymResponseCreateParamsNonStreaming,
cookies: Optional[Mapping[str, str]] = None,
) -> Tuple[NeMoGymResponse, dict]:
"""Implementation of `/v1/responses`; `run` invokes this in-process."""
body = body.model_copy(deep=True)

if isinstance(body.input, str):
Expand All @@ -142,7 +153,9 @@ async def responses(
step = 0
num_tool_calls = 0
model_server_cookies = None # update the cookies on every model response
resources_server_cookies = request.cookies # update the cookies on every resources server response
resources_server_cookies = (
dict(cookies) if cookies else {}
) # update the cookies on every resources server response

reset_threshold = 0
reset_count = 0
Expand Down Expand Up @@ -636,8 +649,9 @@ def save_ckpt() -> None:
pass # best-effort; a stale ckpt won't be re-read because the driver caches this sample

# Propogate any extra cookies necessary for downstream verification
set_cookies: dict[str, str] = {}
for k, v in (*resources_server_cookies.items(), *model_server_cookies.items()):
response.set_cookie(k, v)
set_cookies[k] = v

print(
f"{user_query[:20]}... | FINISHED | Step {step} | Time: {time.monotonic() - time_taken:.2f}s (model {time_taken_model_call:.2f}s, tool {time_taken_tool_call:.2f}s) | Max output tokens: {max_output_tokens} | Missing end thinks: {missing_end_think_count}"
Expand All @@ -648,7 +662,7 @@ def save_ckpt() -> None:
model_response.reset_count = reset_count
model_response.num_tool_calls = num_tool_calls
model_response.metadata = {"missing_end_think_count": str(missing_end_think_count)}
return model_response
return model_response, set_cookies

async def run(self, request: Request, body: BrowsecompAgentRunRequest) -> BrowsecompAgentVerifyResponse:
cookies = request.cookies
Expand All @@ -668,16 +682,9 @@ async def run(self, request: Request, body: BrowsecompAgentRunRequest) -> Browse
body.responses_create_params.metadata["task_index"] = str(body._ng_task_index)
body.responses_create_params.metadata["attempt"] = str(0)

response = await self.server_client.post(
server_name=self.config.name,
url_path="/v1/responses",
json=body.responses_create_params,
cookies=cookies,
)
await raise_for_status(response)
cookies = response.cookies

response_json = await get_response_json(response)
inproc_response, set_cookies = await self._responses(body.responses_create_params, cookies)
cookies = set_cookies
response_json = inproc_response.model_dump()

verify_request = BrowsecompAgentVerifyRequest.model_validate(body.model_dump() | {"response": response_json})

Expand Down
18 changes: 9 additions & 9 deletions responses_api_agents/claude_code_agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,13 @@ async def responses(
request: Request,
body: NeMoGymResponseCreateParamsNonStreaming = Body(),
) -> NeMoGymResponse:
return await self._responses(body)

async def _responses(
self,
body: NeMoGymResponseCreateParamsNonStreaming,
) -> NeMoGymResponse:
"""Implementation of `/v1/responses`; `run` invokes this in-process."""
body = body.model_copy(deep=True)
if isinstance(body.input, str):
body.input = [NeMoGymEasyInputMessage(role="user", content=body.input)]
Expand Down Expand Up @@ -405,15 +412,8 @@ async def run(self, request: Request, body: ClaudeCodeAgentRunRequest) -> Claude
await raise_for_status(seed_resp)
cookies = seed_resp.cookies

agent_resp = await self.server_client.post(
server_name=self.config.name,
url_path="/v1/responses",
json=body.responses_create_params,
cookies=cookies,
)
await raise_for_status(agent_resp)
cookies = agent_resp.cookies
agent_resp_json = await get_response_json(agent_resp)
inproc_resp = await self._responses(body.responses_create_params)
agent_resp_json = inproc_resp.model_dump()

verify_resp = await self.server_client.post(
server_name=self.config.resources_server.name,
Expand Down
36 changes: 22 additions & 14 deletions responses_api_agents/cvdp_agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from typing import List
from typing import List, Mapping, Optional, Tuple

from fastapi import Request, Response
from pydantic import ConfigDict, ValidationError
Expand Down Expand Up @@ -68,6 +68,17 @@ async def responses(
response: Response,
body: NeMoGymResponseCreateParamsNonStreaming = Body(),
) -> NeMoGymResponse:
result, set_cookies = await self._responses(body, request.cookies)
for k, v in set_cookies.items():
response.set_cookie(k, v)
return result

async def _responses(
self,
body: NeMoGymResponseCreateParamsNonStreaming,
cookies: Optional[Mapping[str, str]] = None,
) -> Tuple[NeMoGymResponse, dict]:
"""Implementation of `/v1/responses`; `run` invokes this in-process."""
body = body.model_copy(deep=True)

if isinstance(body.input, str):
Expand All @@ -77,7 +88,9 @@ async def responses(
usage = None
step = 0
model_server_cookies = None # update the cookies on every model response
resources_server_cookies = request.cookies # update the cookies on every resources server response
resources_server_cookies = (
dict(cookies) if cookies else {}
) # update the cookies on every resources server response

while True:
step += 1
Expand Down Expand Up @@ -148,12 +161,13 @@ async def responses(
break

# Propogate any extra cookies necessary for downstream verification
set_cookies: dict[str, str] = {}
for k, v in (*resources_server_cookies.items(), *model_server_cookies.items()):
response.set_cookie(k, v)
set_cookies[k] = v

model_response.output = new_outputs
model_response.usage = usage
return model_response
return model_response, set_cookies

async def run(self, request: Request, body: SimpleAgentRunRequest) -> SimpleAgentVerifyResponse:
cookies = request.cookies
Expand All @@ -179,24 +193,18 @@ async def run(self, request: Request, body: SimpleAgentRunRequest) -> SimpleAgen
retries_left = self.config.llm_parse_retries
while True:
try:
response = await self.server_client.post(
server_name=self.config.name,
url_path="/v1/responses",
json=body.responses_create_params,
cookies=cookies,
)
await raise_for_status(response)
cookies = response.cookies
inproc_response, set_cookies = await self._responses(body.responses_create_params, cookies)
attempt_cookies = set_cookies

verify_request = SimpleAgentVerifyRequest.model_validate(
body.model_dump() | {"response": await get_response_json(response)}
body.model_dump() | {"response": inproc_response.model_dump()}
)

verify_response = await self.server_client.post(
server_name=self.config.resources_server.name,
url_path="/verify",
json=verify_request.model_dump(),
cookies=cookies,
cookies=attempt_cookies,
)
await raise_for_status(verify_response)
result = SimpleAgentVerifyResponse.model_validate(await get_response_json(verify_response))
Expand Down
38 changes: 22 additions & 16 deletions responses_api_agents/finance_agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import json
import logging
import re
from typing import Any, List, Optional
from typing import Any, List, Mapping, Optional, Tuple

from fastapi import Request, Response
from pydantic import ConfigDict, Field
Expand Down Expand Up @@ -161,6 +161,17 @@ async def responses(
response: Response,
body: NeMoGymResponseCreateParamsNonStreaming = Body(),
) -> NeMoGymResponse:
result, set_cookies = await self._responses(body, request.cookies)
for k, v in set_cookies.items():
response.set_cookie(k, v)
return result

async def _responses(
self,
body: NeMoGymResponseCreateParamsNonStreaming,
cookies: Optional[Mapping[str, str]] = None,
) -> Tuple[NeMoGymResponse, dict]:
"""Implementation of `/v1/responses`; `run` invokes this in-process."""
body = body.model_copy(deep=True)

if isinstance(body.input, str):
Expand All @@ -171,7 +182,7 @@ async def responses(
step = 0
last_model_response: Optional[NeMoGymResponse] = None
model_server_cookies = None
resources_server_cookies = request.cookies
resources_server_cookies = dict(cookies) if cookies else {}

done_tools_set = set(self.config.done_tools)
max_steps = self.config.max_steps
Expand Down Expand Up @@ -316,15 +327,16 @@ async def responses(
tool_choice="auto",
)

cookie_items = list(resources_server_cookies.items())
set_cookies: dict[str, str] = {}
for k, v in resources_server_cookies.items():
set_cookies[k] = v
if model_server_cookies:
cookie_items.extend(model_server_cookies.items())
for k, v in cookie_items:
response.set_cookie(k, v)
for k, v in model_server_cookies.items():
set_cookies[k] = v

last_model_response.output = new_outputs
last_model_response.usage = usage
return last_model_response
return last_model_response, set_cookies

async def run(self, request: Request, body: FinanceAgentRunRequest) -> FinanceAgentVerifyResponse:
try:
Expand Down Expand Up @@ -359,17 +371,11 @@ async def _run_inner(self, request: Request, body: FinanceAgentRunRequest) -> Fi
await raise_for_status(seed_session_response)
cookies = seed_session_response.cookies

response = await self.server_client.post(
server_name=self.config.name,
url_path="/v1/responses",
json=body.responses_create_params,
cookies=cookies,
)
await raise_for_status(response)
cookies = response.cookies
inproc_response, set_cookies = await self._responses(body.responses_create_params, cookies)
cookies = set_cookies

verify_request = FinanceAgentVerifyRequest.model_validate(
body.model_dump() | {"response": await get_response_json(response)}
body.model_dump() | {"response": inproc_response.model_dump()}
)

verify_response = await self.server_client.post(
Expand Down
18 changes: 9 additions & 9 deletions responses_api_agents/hermes_agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,13 @@ async def responses(
request: Request,
body: NeMoGymResponseCreateParamsNonStreaming = Body(),
) -> NeMoGymResponse:
return await self._responses(body)

async def _responses(
self,
body: NeMoGymResponseCreateParamsNonStreaming,
) -> NeMoGymResponse:
"""Implementation of `/v1/responses`; `run` invokes this in-process."""
from run_agent import AIAgent # from hermes-agent on path

body = body.model_copy(deep=True)
Expand Down Expand Up @@ -315,15 +322,8 @@ async def run(self, request: Request, body: HermesAgentRunRequest) -> HermesAgen
await raise_for_status(seed_resp)
cookies = seed_resp.cookies

agent_resp = await self.server_client.post(
server_name=self.config.name,
url_path="/v1/responses",
json=body.responses_create_params,
cookies=cookies,
)
await raise_for_status(agent_resp)
cookies = agent_resp.cookies
agent_resp_json = await get_response_json(agent_resp)
inproc_resp = await self._responses(body.responses_create_params)
agent_resp_json = inproc_resp.model_dump()

verify_resp = await self.server_client.post(
server_name=self.config.resources_server.name,
Expand Down
30 changes: 20 additions & 10 deletions responses_api_agents/langgraph_agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from abc import abstractmethod
from typing import Any
from typing import Any, Mapping, Optional, Tuple

from fastapi import Body, Request, Response
from pydantic import ConfigDict
Expand Down Expand Up @@ -58,17 +58,29 @@ def extract_model_response(self, final_state: dict) -> NeMoGymResponse:
async def responses(
self, request: Request, response: Response, body: NeMoGymResponseCreateParamsNonStreaming = Body()
) -> NeMoGymResponse:
initial_state = await self.get_initial_state(body, request.cookies)
result, set_cookies = await self._responses(body, request.cookies)
for k, v in set_cookies.items():
response.set_cookie(k, v)
return result

async def _responses(
self,
body: NeMoGymResponseCreateParamsNonStreaming,
cookies: Optional[Mapping[str, str]] = None,
) -> Tuple[NeMoGymResponse, dict]:
"""Implementation of `/v1/responses`; subclass `run` methods invoke this in-process."""
initial_state = await self.get_initial_state(body, dict(cookies) if cookies else {})
final_state = await self.graph.ainvoke(initial_state)

set_cookies: dict[str, str] = {}
if "cookies" in final_state:
for k, v in final_state["cookies"].items():
response.set_cookie(k, v)
set_cookies[k] = v

model_response = self.extract_model_response(final_state)
outputs = self.extract_outputs(final_state)
model_response.output = outputs
return model_response
return model_response, set_cookies

async def run(self, request: Request, body: BaseRunRequest) -> BaseVerifyResponse:
cookies = request.cookies
Expand All @@ -82,18 +94,16 @@ async def run(self, request: Request, body: BaseRunRequest) -> BaseVerifyRespons
await raise_for_status(seed)
cookies = seed.cookies

resp = await self.server_client.post(
server_name=self.config.name, url_path="/v1/responses", json=body.responses_create_params, cookies=cookies
)
await raise_for_status(resp)
inproc_resp, set_cookies = await self._responses(body.responses_create_params, cookies)
cookies = set_cookies

verify_request_dict = body.model_dump() | {"response": await get_response_json(resp)}
verify_request_dict = body.model_dump() | {"response": inproc_resp.model_dump()}

verify = await self.server_client.post(
server_name=self.config.resources_server.name,
url_path="/verify",
json=verify_request_dict,
cookies=resp.cookies,
cookies=cookies,
)
await raise_for_status(verify)
return BaseVerifyResponse.model_validate(await get_response_json(verify))
10 changes: 4 additions & 6 deletions responses_api_agents/langgraph_agent/orchestrator_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,20 +234,18 @@ async def run(self, request: Request, body: OrchestratorRunRequest) -> Orchestra
await raise_for_status(seed)
cookies = seed.cookies

resp = await self.server_client.post(
server_name=self.config.name, url_path="/v1/responses", json=body.responses_create_params, cookies=cookies
)
await raise_for_status(resp)
inproc_resp, set_cookies = await self._responses(body.responses_create_params, cookies)
cookies = set_cookies

verify_request = OrchestratorVerifyRequest.model_validate(
body.model_dump() | {"response": await get_response_json(resp)}
body.model_dump() | {"response": inproc_resp.model_dump()}
)

verify = await self.server_client.post(
server_name=self.config.resources_server.name,
url_path="/verify",
json=verify_request.model_dump(),
cookies=resp.cookies,
cookies=cookies,
)
await raise_for_status(verify)
return OrchestratorVerifyResponse.model_validate(await get_response_json(verify))
Expand Down
Loading
Loading