""" Tau-Bench Integration for slime Training This module provides the main interface for training agents in tau-bench environments using the slime framework. It handles agent-environment interactions and converts results to the format expected by slime's training pipeline. """ import logging import os from typing import Any from tau_bench.envs import get_env from tau_bench.types import RunConfig from trainable_agents import InteractionResult, Status, agent_factory from slime.utils.types import Sample # Set up logger for this module logger = logging.getLogger(__name__) # Tau-bench configuration TAU_CONFIGS = { "env": "retail", # Select between ["retail", "airline"] "agent_strategy": "tool-calling", # Select between ["tool-calling", "act", "react", "few-shot"] "user_model": "gemini-2.5-flash-lite", # Cheap Model for user simulator "task_split": "train", # Select between ["train", "test", "dev"] for retail "user_strategy": "llm", # Select between ["llm", "react", "verify", "reflection"] "model_provider": "auto_router", # Unused, required "model": "qwen3-4b", # Unused, required "user_model_provider": "gemini", } # Replace with your actual API key for user sim GEMINI_API_KEY = "NONE" os.environ["GEMINI_API_KEY"] = GEMINI_API_KEY tau_config = RunConfig(**TAU_CONFIGS) def res_to_sample(res: InteractionResult, task_index: int) -> Sample: """ Convert InteractionResult to Sample format for slime training. This function transforms the tau-bench interaction result into the format expected by slime's training pipeline, handling status mapping and response length calculation. Args: res: InteractionResult from tau-bench agent task_index: Index of the task being processed Returns: Sample object for slime training """ # Map tau-bench status to slime status status_mapping = { Status.COMPLETED: "completed", Status.TRUNCATED: "truncated", Status.ABORTED: "aborted", } status = status_mapping.get(res.status) # Debug logging for response tracking logger.debug( f"res_to_sample: response_length=" f"{res.response_length if hasattr(res, 'response_length') else 'None'}, " f"loss_mask_len={len(res.loss_mask) if res.loss_mask else 'None'}, " f"tokens_len={len(res.tokens) if res.tokens else 'None'}" ) # Create sample with basic information sample = Sample( index=task_index, prompt=res.prompt, tokens=res.tokens, response=res.response, reward=res.reward, loss_mask=res.loss_mask, status=status, metadata=res.info, ) # Ensure response_length is set correctly if hasattr(res, "response_length"): sample.response_length = res.response_length else: # Fallback: calculate from loss_mask if available if res.loss_mask: # loss_mask only contains response part, so length equals response_length sample.response_length = len(res.loss_mask) elif res.tokens: # If no loss_mask available, use total tokens as fallback sample.response_length = len(res.tokens) else: sample.response_length = 0 logger.debug(f"res_to_sample: Set response_length={sample.response_length}") return sample async def generate(args: dict[str, Any], sample: Sample, sampling_params: dict) -> Sample: """ Generate a complete agent-environment interaction trajectory for tau-bench. This is the main entry point for slime training. It creates a tau-bench environment, initializes a trainable agent, and executes a full interaction trajectory. The result is converted to slime's Sample format for training. Args: args: Rollout arguments from slime training pipeline sample: Sample containing task index in prompt field sampling_params: LLM sampling parameters Returns: Sample object containing the complete interaction trajectory Raises: AssertionError: If partial rollout is requested (not supported) """ # Validate arguments assert not args.partial_rollout, "Partial rollout is not supported for tau-bench interactions." # Extract task index from sample prompt task_index = int(sample.prompt) logger.info(f"Starting agent-environment interaction for task {task_index}") # Initialize tau-bench environment env = get_env( env_name=tau_config.env, user_strategy=tau_config.user_strategy, user_model=tau_config.user_model, user_provider=tau_config.user_model_provider, task_split=tau_config.task_split, task_index=task_index, ) # Create trainable agent agent = agent_factory( tools_info=env.tools_info, wiki=env.wiki, config=tau_config, rollout_args=args, sampling_params=sampling_params, ) # Execute agent-environment interaction # Note: The sample.prompt field contains the task index for repeatability interaction_result = await agent.asolve(env, agent.rollout_args, agent.sampling_params, task_index) # Convert to slime Sample format result_sample = res_to_sample(interaction_result, task_index) logger.info(f"Finished agent-environment interaction for task {task_index}") return result_sample