mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Add Agent Framework Lab Lightning package with RL training examples (#937)
* add math agent * . * update * update debug mode * add tau2 training * . * . * . * . * add tests * . * revert observability * update readme * fix task serialization issue * fix exception * add inline docs * update readme * update pyproject toml * minor fix * update and use git lfs * update * update ignore file to use lab specific * fix type * update depedency --------- Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
21a60aeb35
commit
b8df0cd03f
@@ -198,13 +198,4 @@ temp*/
|
||||
.tmp/
|
||||
.temp/
|
||||
|
||||
# GAIA data directories
|
||||
data_gaia_hub/
|
||||
**/data_gaia_hub/
|
||||
python/packages/lab/gaia/**/*.jsonl
|
||||
|
||||
# TAU2 data directories
|
||||
python/packages/lab/tau2/**/data/
|
||||
python/packages/lab/tau2/**/results/
|
||||
|
||||
agents.md
|
||||
|
||||
@@ -1 +1,13 @@
|
||||
test-results.xml
|
||||
test-results.xml
|
||||
|
||||
# GAIA data directories
|
||||
data_gaia_hub/
|
||||
**/data_gaia_hub/
|
||||
gaia/**/*.jsonl
|
||||
|
||||
# Lightning data directories
|
||||
lightning/**/data/tau2
|
||||
|
||||
# TAU2 data directories
|
||||
tau2/**/data/
|
||||
tau2/**/results/
|
||||
|
||||
@@ -9,7 +9,6 @@ Lab modules are not part of the core framework and may experience breaking chang
|
||||
Lab modules are extensions to the core Agent Framework that fall into
|
||||
one of the following categories:
|
||||
|
||||
1. Incubation of new features that may get incorporated by the core framework.
|
||||
1. Incubation of new features that may get incorporated by the core framework.
|
||||
2. Research prototypes built on the core framework.
|
||||
3. Benchmarks and experimentation tools.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
assets/ filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -1,6 +1,8 @@
|
||||
# Agent Framework Lab - Lightning
|
||||
|
||||
RL Module for Microsoft Agent Framework
|
||||
**Agent Framework Lab Lightning** is a specialized package that integrates [Microsoft Agent Framework](https://github.com/microsoft/agent-framework) with [Agent-lightning](https://github.com/microsoft/agent-lightning) to provide reinforcement learning (RL) training capabilities for AI agents.
|
||||
|
||||
This package enables you to train and fine-tune agents using advanced RL algorithms from VERL (e.g., GRPO, PPO, Reinforce++) with support for distributed training, multi-GPU setups, and comprehensive monitoring. It also supports complex multi-turn agent interactions during training and optimization techniques like prompt optimization. See the [Agent-lightning documentation](https://microsoft.github.io/agent-lightning/stable/) for details.
|
||||
|
||||
> **Note**: This module is part of the consolidated `agent-framework-lab` package. Install the package with the `lightning` extra to use this module.
|
||||
|
||||
@@ -12,44 +14,173 @@ Install the agent-framework-lab package with Lightning dependencies:
|
||||
pip install "agent-framework-lab[lightning]"
|
||||
```
|
||||
|
||||
## Usage
|
||||
### Optional Dependencies
|
||||
|
||||
```python
|
||||
from agent_framework.lab.lightning import YourClass
|
||||
```bash
|
||||
# For math-related training
|
||||
pip install agent-framework-lab[lightning,math]
|
||||
|
||||
# Your usage example here
|
||||
instance = YourClass()
|
||||
# For tau2 benchmarking
|
||||
pip install agent-framework-lab[lightning,tau2]
|
||||
```
|
||||
|
||||
## Overview
|
||||
To prepare for RL training, you'll also need to install dependencies like PyTorch, Ray, and vLLM. See the [Agent-lightning setup instructions](https://github.com/microsoft/agent-lightning) for more details.
|
||||
|
||||
Brief description of what this lab package provides and its main features.
|
||||
## Usage Patterns
|
||||
|
||||
## Features
|
||||
The basic usage pattern follows these steps:
|
||||
|
||||
- Feature 1: Description
|
||||
- Feature 2: Description
|
||||
- Feature 3: Description
|
||||
1. **Prepare your dataset** as a list of samples (typically dictionaries)
|
||||
2. **Create an agent function** that processes samples and returns evaluation scores
|
||||
3. **Decorate with `@agentlightning.rollout`** to enable training
|
||||
4. **Configure and run training** with the `agentlightning.Trainer` class
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Usage
|
||||
### Example Implementation
|
||||
|
||||
```python
|
||||
from agent_framework.lab.lightning import YourClass
|
||||
from agent_framework.lab.lightning import init
|
||||
from agentlightning import rollout, Trainer, LLM, Dataset
|
||||
from agentlightning.algorithm.verl import VERL
|
||||
|
||||
# Example usage
|
||||
TaskType = Any
|
||||
|
||||
@rollout
|
||||
async def math_agent(task: TaskType, llm: LLM) -> float:
|
||||
"""A function that solves a math problem and returns the evaluation score."""
|
||||
async with (
|
||||
MCPStdioTool(name="calculator", command="uvx", args=["mcp-server-calculator"]) as mcp_server,
|
||||
ChatAgent(
|
||||
chat_client=OpenAIChatClient(
|
||||
ai_model_id=llm.model,
|
||||
api_key="your-api-key",
|
||||
base_url=llm.endpoint,
|
||||
),
|
||||
name="MathAgent",
|
||||
instructions="Solve the math problem and output answer after ###",
|
||||
temperature=llm.sampling_parameters.get("temperature", 0.0),
|
||||
) as agent,
|
||||
):
|
||||
result = await agent.run(task["question"], tools=mcp_server)
|
||||
# Your evaluation logic here...
|
||||
return evaluation_score
|
||||
|
||||
# Training configuration
|
||||
config = {
|
||||
"data": {"train_batch_size": 8},
|
||||
"trainer": {"total_epochs": 2, "n_gpus_per_node": 1},
|
||||
# ... additional config
|
||||
}
|
||||
|
||||
# Initialize agent-framework to send telemetry data to agent-lightning's observability backend
|
||||
init()
|
||||
|
||||
trainer = Trainer(algorithm=VERL(config), n_workers=2)
|
||||
# Both train_dataset and val_dataset are lists of TaskType
|
||||
trainer.fit(math_agent, train_dataset, val_data=val_dataset)
|
||||
```
|
||||
|
||||
### Advanced Usage
|
||||
## Example 1: Training a Math Agent
|
||||
|
||||
```python
|
||||
# More advanced examples
|
||||
This example trains an agent that uses an MCP calculator tool to solve math problems. The dataset is a small subset from the [Calc-X](https://huggingface.co/datasets/MU-NLPC/Calc-X) dataset. The Agent-lightning team has also experimented with a similar agent using a larger dataset. See [this example](https://github.com/microsoft/agent-lightning/tree/a63197355cc23b5b235c49fe7c20b54f9d4ebcd2/examples/calc_x) for more details.
|
||||
|
||||
Running this example requires a minimum of 40GB GPU memory. If you don't have enough GPU memory, you can use a smaller model like `Qwen2.5-0.5B-Instruct`, though the results won't be as good. To run the example:
|
||||
|
||||
```bash
|
||||
cd samples
|
||||
# Run the ray cluster (see the troubleshooting section for more details)
|
||||
ray start --head --dashboard-host=0.0.0.0
|
||||
# Run the training script
|
||||
python train_math_agent.py
|
||||
```
|
||||
|
||||
## API Reference
|
||||
To debug the agent used in the example, you can run the script with the `--debug` flag:
|
||||
|
||||
Document your main classes and functions here.
|
||||
```bash
|
||||
python train_math_agent.py --debug
|
||||
```
|
||||
|
||||
The training curve below shows results with Qwen2.5-1.5B-Instruct and GRPO. Validation accuracy increases from 10% to 35% in the first 8 steps, then begins to overfit.
|
||||
|
||||

|
||||
|
||||
## Example 2: Training a Tau2 Agent
|
||||
|
||||
This advanced example demonstrates training on complex multi-agent scenarios using the Tau2 benchmark. It features a multi-agent setup with an assistant agent and a user simulator agent, training the assistant while keeping the user simulator fixed. The example incorporates a multi-step workflow with tool usage and complex evaluation metrics. Currently, training uses the airline domain with a 50/50 split between training and validation data.
|
||||
|
||||
Before running this example, please read the [agent-lightning-lab-tau2](../tau2/README.md) documentation and follow the setup instructions.
|
||||
|
||||
To run the example:
|
||||
|
||||
```bash
|
||||
# Set required environment variables
|
||||
export TAU2_DATA_DIR="/path/to/tau2/data"
|
||||
|
||||
# Used for user simulator and LLM judge
|
||||
export OPENAI_BASE_URL="your-endpoint"
|
||||
export OPENAI_API_KEY="your-key"
|
||||
|
||||
# Used for tracking on Weights & Biases
|
||||
export WANDB_API_KEY="your-key"
|
||||
|
||||
# Run the ray cluster
|
||||
ray start --head --dashboard-host=0.0.0.0
|
||||
|
||||
# Train the tau2 agent
|
||||
cd samples
|
||||
python samples/train_tau2_agent.py
|
||||
|
||||
# Debug mode
|
||||
python samples/train_tau2_agent.py --debug
|
||||
```
|
||||
|
||||
This example uses more advanced Agent-lightning features compared to the math example. It's based on the `LitAgent` class rather than the `@rollout` decorator and involves concepts like resources and agent filtering. We recommend reading the [Agent-lightning documentation](https://microsoft.github.io/agent-lightning/stable/) to learn more.
|
||||
|
||||
Results with Qwen2.5-1.5B-Instruct and GRPO are shown below. Validation accuracy improves from 28% to 40% over 8 epochs.
|
||||
|
||||

|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Ray Connection Issues
|
||||
|
||||
Agent-lightning uses VERL for RL training, which depends on Ray. To avoid issues, it's recommended to start Ray manually beforehand. If you encounter Ray startup problems:
|
||||
|
||||
```bash
|
||||
# Stop existing Ray processes
|
||||
ray stop
|
||||
|
||||
# Start Ray with debugging enabled
|
||||
env RAY_DEBUG=legacy HYDRA_FULL_ERROR=1 VLLM_USE_V1=1 ray start --head --dashboard-host=0.0.0.0
|
||||
```
|
||||
|
||||
**Important**: Run Ray commands in the same directory as your training script. Set any required environment variables (`WANDB_API_KEY`, `HF_TOKEN`) before starting Ray.
|
||||
|
||||
### GPU Memory Issues
|
||||
|
||||
1. **Reduce `gpu_memory_utilization`** to <0.8
|
||||
2. **Enable FSDP offloading**:
|
||||
```python
|
||||
"fsdp_config": {
|
||||
"param_offload": True,
|
||||
"optimizer_offload": True,
|
||||
}
|
||||
```
|
||||
3. **Decrease batch sizes**:
|
||||
- `train_batch_size`
|
||||
- `ppo_mini_batch_size`
|
||||
- `log_prob_micro_batch_size_per_gpu`
|
||||
|
||||
### Agent Debugging
|
||||
|
||||
Always test your agent before training:
|
||||
|
||||
```bash
|
||||
# Use debug mode to validate agent behavior
|
||||
python your_training_script.py --debug
|
||||
|
||||
# Check agent responses and evaluation logic
|
||||
# Ensure proper tool integration and result extraction
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -57,4 +188,4 @@ This package is part of the Microsoft Agent Framework Lab. Please see the main r
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
|
||||
@@ -2,11 +2,22 @@
|
||||
|
||||
"""RL Module for Microsoft Agent Framework."""
|
||||
|
||||
# ruff: noqa: F403
|
||||
|
||||
import importlib.metadata
|
||||
|
||||
from agent_framework.observability import OBSERVABILITY_SETTINGS
|
||||
from agentlightning import * # type: ignore
|
||||
|
||||
try:
|
||||
__version__ = importlib.metadata.version(__name__)
|
||||
except importlib.metadata.PackageNotFoundError:
|
||||
__version__ = "0.0.0" # Fallback for development mode
|
||||
|
||||
__all__: list[str] = []
|
||||
|
||||
def init() -> None:
|
||||
"""Initialize the agent-framework-lab-lightning for training."""
|
||||
OBSERVABILITY_SETTINGS.enable_otel = True
|
||||
|
||||
|
||||
__all__: list[str] = ["init"]
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
{"id": "svamp__chal-551", "question": "Robin has some packages of gum. There are 7 pieces in each package. Robin has 6 extra pieces of gum. In all the number of pieces of gums robin has is 41. How many packages does Robin have?", "chain": "<gadget id=\"calculator\">41 - 6</gadget>\n<output>35</output>\n\n<gadget id=\"calculator\">35 / 7</gadget>\n<output>5</output>\n\n<result>5</result>", "result": "5", "source": "calc"}
|
||||
{"id": "ape210k__00027150", "question": "2 meters of floral cloth, how much rice is left after 80% is used", "chain": "<gadget id=\"calculator\">80 / 100</gadget>\n<output>4/5 = around 0.8</output>\n\n<gadget id=\"calculator\">1 - (4/5)</gadget>\n<output>1/5 = around 0.2</output>\n\n<gadget id=\"calculator\">2 * (1/5)</gadget>\n<output>2/5 = around 0.4</output>\n\n<result>2/5 = around 0.4</result>", "result": "2/5", "source": "calc"}
|
||||
{"id": "ape210k__00287396", "question": "There are two schools, A and B. School A has 525 students, and school B has 50 fewer students than school A. How many students are there in school B?", "chain": "<gadget id=\"calculator\">525 * 2</gadget>\n<output>1_050</output>\n\n<gadget id=\"calculator\">1_050 - 50</gadget>\n<output>1_000</output>\n\n<result>1_000</result>", "result": "1_000", "source": "calc"}
|
||||
{"id": "gsm8k__xtQ5d23fzgEAhUdB", "question": "If Mark weighs 150 pounds and Susan weighs 20 pounds less than Mark. And their friend Bob weighs twice as much as Susan. What is the average weight of the 3 friends?", "chain": "Susan weighs 150 pounds - 20 pounds = \n<gadget id=\"calculator\">150-20</gadget>\n<output>130</output>\n130 pounds.\nBob weighs 2 * 130 pounds = \n<gadget id=\"calculator\">2*130</gadget>\n<output>260</output>\n260 pounds.\nThe friends total weight is 150 + 130 + 260 pounds = \n<gadget id=\"calculator\">150+130+260</gadget>\n<output>540</output>\n540 pounds.\nThe friends' average weight is 540 pounds / 3 = \n<gadget id=\"calculator\">540/3</gadget>\n<output>180</output>\n180 pounds.\n\n<result>180</result>", "result": "180", "source": "calc"}
|
||||
{"id": "svamp__chal-741", "question": "He had a total of 40 saltwater animals in different aquariums. Each aquarium has 2 animals in it. How many aquariums did he have?", "chain": "<gadget id=\"calculator\">40 / 2</gadget>\n<output>20</output>\n\n<result>20</result>", "result": "20", "source": "calc"}
|
||||
{"id": "asdiv_a__nluds-0023", "question": "You have collected 7 crickets. How many more crickets do you need to collect to have 11 crickets?", "chain": "<gadget id=\"calculator\">11 - 7</gadget>\n<output>4</output>\n\n<result>4</result>", "result": "4", "source": "calc"}
|
||||
{"id": "gsm8k__0oOjz5Ub66DF4inZ", "question": "There are 6 trees in Chris's yard. Ferdinand has half the number of trees that Chris has. Harry has 5 more than twice the number of trees that Ferdinand has. How many more trees are in Harry's yard than Ferdinand's yard?", "chain": "Ferdinand:6/2=\n<gadget id=\"calculator\">6/2</gadget>\n<output>3</output>\n3 trees.\nHarry:5+2(3)=5+6=11 trees\n11-3=\n<gadget id=\"calculator\">11-3</gadget>\n<output>8</output>\n8 trees.\n\n<result>8</result>", "result": "8", "source": "calc"}
|
||||
{"id": "ape210k__00565195", "question": "During the May 1st period, Xiaoqiang\u2019s family went on a trip to other places. The planned consumption was 2,000 yuan, but the actual consumption was 1,800 yuan. How much less was the actual consumption than the plan?", "chain": "<gadget id=\"calculator\">2_000 - 1_800</gadget>\n<output>200</output>\n\n<gadget id=\"calculator\">200 / 2_000</gadget>\n<output>1/10 = around 0.1</output>\n\n<result>1/10 = around 0.1</result>", "result": "1/10", "source": "calc"}
|
||||
{"id": "mawps__E0wRRdRDwTmdqH2u", "question": "Milton had 238 peach. William clasped some peach. Now Milton has 51 peach. How many did William claspeds?", "chain": "<gadget id=\"calculator\">238 - 51</gadget>\n<output>187</output>\n\n<result>187</result>", "result": "187", "source": "calc"}
|
||||
{"id": "asdiv_a__nluds-0318", "question": "The map led them through the forest and into a cave. To open the cave doors, they need to put weights on the switch. If the switch already has 234 lbs. of weights and the total needed is 712 lbs.,, how much more weight to they need to add?", "chain": "<gadget id=\"calculator\">712 - 234</gadget>\n<output>478</output>\n\n<result>478</result>", "result": "478", "source": "calc"}
|
||||
{"id": "ape210k__00965281", "question": "The annual interest rate of the five-year national debt is 2.75%. If a person buys a national debt of 20,000 yuan, what is the total amount of principal and interest after maturity?", "chain": "<gadget id=\"calculator\">2.75 / 100</gadget>\n<output>0.0275</output>\n\n<gadget id=\"calculator\">20_000 * 0.0275 * 5</gadget>\n<output>2_750</output>\n\n<gadget id=\"calculator\">20_000 + 2_750</gadget>\n<output>22_750</output>\n\n<result>22_750</result>", "result": "22_750", "source": "calc"}
|
||||
{"id": "svamp__chal-289", "question": "Jack received 6 emails in the morning and 8 emails in the afternoon. How many more emails did Jack receive in the afternoon than in the morning?", "chain": "<gadget id=\"calculator\">8 - 6</gadget>\n<output>2</output>\n\n<result>2</result>", "result": "2", "source": "calc"}
|
||||
{"id": "ape210k__00829979", "question": "The fifth grade students participate in the big break exercise, and 12 people or 18 people can be divided into a row. If the number of students is less than 200, how many students can participate in the big break exercise this time?", "chain": "<gadget id=\"calculator\">36 * 5</gadget>\n<output>180</output>\n\n<result>180</result>", "result": "180", "source": "calc"}
|
||||
{"id": "ape210k__00909867", "question": "A and B process 1200 parts at the same time, and the plan is to complete it in 6 hours. A processes 80 parts per hour. To complete the work on time, how many parts does B need to process per hour? (column equations to solve problems)", "chain": "<gadget id=\"calculator\">80 * 6</gadget>\n<output>480</output>\n\n<gadget id=\"calculator\">1_200 - 480</gadget>\n<output>720</output>\n\n<gadget id=\"calculator\">720 / 6</gadget>\n<output>120</output>\n\n<result>120</result>", "result": "120", "source": "calc"}
|
||||
{"id": "svamp__chal-972", "question": "A mailman has to give 4 pieces of junk mail to each house in each of the 16 blocks. If there are 17 houses in each block, how many pieces of junk mail should he give in total?", "chain": "<gadget id=\"calculator\">4 * 17</gadget>\n<output>68</output>\n\n<gadget id=\"calculator\">68 * 16</gadget>\n<output>1_088</output>\n\n<result>1088</result>", "result": "1_088", "source": "calc"}
|
||||
{"id": "aqua_rat__j7vMuYEEajqH6GTH", "question": "5 horses are in a race. Mr.Jain selects two of horses at random and bets on them. The probability that he selected the winning horse is Choose the correct choice: A) 1/5 B) 2/5 C) 3/5 D) 4/5 E) 6/5", "chain": "There are 5 horses. Probability of winning for each horse = 1/5. Probability of winning with 2 selected horses= (1/5)+(1/5)= 2/5. Answer is 2/5. ANSWER:2/5\n<result>B</result>", "result": "B", "source": "calc"}
|
||||
{"id": "asdiv_a__nluds-0263", "question": "Feeling good about what he did, Mr. Anderson decided to continue giving to others. He went around the city and gave clothes to homeless people. If he gave 589 shirts and 345 trousers,, how many pieces of clothing did he gave out in total?", "chain": "<gadget id=\"calculator\">589 + 345</gadget>\n<output>934</output>\n\n<result>934</result>", "result": "934", "source": "calc"}
|
||||
{"id": "svamp__chal-968", "question": "Mary is baking a cake. The recipe calls for 10 cups of flour 2 cups of sugar and 80 cups of salt. She already put in 7 cups of flour. How many more cups of flour than cups of sugar does she need to add now?", "chain": "<gadget id=\"calculator\">10 - 7</gadget>\n<output>3</output>\n\n<gadget id=\"calculator\">3 - 2</gadget>\n<output>1</output>\n\n<result>1</result>", "result": "1", "source": "calc"}
|
||||
{"id": "gsm8k__aIzJoU5IRgriERup", "question": "A tub of ice cream costing $13 is now sold at $11. A packet of milk was sold at a discount of $0.5. How much will you save if you buy 2 tubs of ice cream and 4 packets of milk?", "chain": "The discount for each tub of ice cream is $13 - $11 = $\n<gadget id=\"calculator\">13-11</gadget>\n<output>2</output>\n2.\nSo the discount for 2 tubs of ice cream is $2 x 2 = $\n<gadget id=\"calculator\">2*2</gadget>\n<output>4</output>\n4.\nThe total discount for 4 packets of milk is $0.5 x 4 = $\n<gadget id=\"calculator\">0.5*4</gadget>\n<output>2</output>\n2.\nYou will save $4 + $2 = $6 for 2 tubs of ice cream and 4 packets of milk.\n\n<result>6</result>", "result": "6", "source": "calc"}
|
||||
{"id": "ape210k__00623575", "question": "In the art group, boys are girls (4/5), how much less boys than girls.", "chain": "<gadget id=\"calculator\">4 / 5</gadget>\n<output>4/5 = around 0.8</output>\n\n<gadget id=\"calculator\">1 - (4/5)</gadget>\n<output>1/5 = around 0.2</output>\n\n<gadget id=\"calculator\">(1/5) / 1</gadget>\n<output>1/5 = around 0.2</output>\n\n<result>1/5 = around 0.2</result>", "result": "1/5", "source": "calc"}
|
||||
@@ -0,0 +1,64 @@
|
||||
{"id": "ape210k__00384263", "question": "6.6 minus x (3/2) times equals 5.6.", "chain": "<gadget id=\"calculator\">6.6 - 5.6</gadget>\n<output>1</output>\n\n<gadget id=\"calculator\">3 / 2</gadget>\n<output>3/2 = around 1.5</output>\n\n<gadget id=\"calculator\">1 / (3/2)</gadget>\n<output>2/3 = around 0.666667</output>\n\n<result>2/3 = around 0.666667</result>", "result": "2/3", "source": "calc"}
|
||||
{"id": "ape210k__00469689", "question": "How many degrees of 75\u00b0 can form a right angle?", "chain": "<gadget id=\"calculator\">90 - 75</gadget>\n<output>15</output>\n\n<result>15</result>", "result": "15", "source": "calc"}
|
||||
{"id": "ape210k__00352031", "question": "Wang Li puts a piece of cake on the left side of the balance, and (1/4) piece of cake and a weight of 90 grams on the right side. At this time, the balance is just balanced. How much does a whole cake weigh in grams?", "chain": "<gadget id=\"calculator\">1 / 4</gadget>\n<output>1/4 = around 0.25</output>\n\n<gadget id=\"calculator\">90 / (1/4)</gadget>\n<output>360</output>\n\n<result>360</result>", "result": "360", "source": "calc"}
|
||||
{"id": "ape210k__00569876", "question": "Column calculation: Subtract 30% of (2/5) from 1, divide the difference by (11/50), what is the quotient?", "chain": "<gadget id=\"calculator\">2 / 5</gadget>\n<output>2/5 = around 0.4</output>\n\n<gadget id=\"calculator\">30 / 100</gadget>\n<output>3/10 = around 0.3</output>\n\n<gadget id=\"calculator\">(2/5) * (3/10)</gadget>\n<output>3/25 = around 0.12</output>\n\n<gadget id=\"calculator\">1 - (3/25)</gadget>\n<output>22/25 = around 0.88</output>\n\n<gadget id=\"calculator\">11 / 50</gadget>\n<output>11/50 = around 0.22</output>\n\n<gadget id=\"calculator\">(22/25) / (11/50)</gadget>\n<output>4</output>\n\n<result>4</result>", "result": "4", "source": "calc"}
|
||||
{"id": "ape210k__00767581", "question": "It takes Xiaofang 12 seconds to walk from the first floor to the third floor. At this speed, how many seconds does it take her to go from the third floor to the seventh floor?", "chain": "<gadget id=\"calculator\">3 - 1</gadget>\n<output>2</output>\n\n<gadget id=\"calculator\">12 / 2</gadget>\n<output>6</output>\n\n<gadget id=\"calculator\">7 - 3</gadget>\n<output>4</output>\n\n<gadget id=\"calculator\">6 * 4</gadget>\n<output>24</output>\n\n<result>24</result>", "result": "24", "source": "calc"}
|
||||
{"id": "aqua_rat__0bgRP2fAiH8URR9A", "question": "36 men can complete a piece of work in 18 days. In how many days will 108 men complete the same work ?\nChoose the correct choice\nA) 24 B) 77 C) 6 D) 29 E) 21", "chain": "Explanation: Less Men, means more Days {Indirect Proportion} Let the number of days be x then, 108 : 36 :: 18 : x x = 6 Answer: 6) 6 days\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
{"id": "ape210k__00469555", "question": "The average score of Li Hong's Chinese unit test in the first three units of this semester is 92 points, and the average score of the first two units is 93 points. What is the score of the third language test?", "chain": "<gadget id=\"calculator\">92 * 3</gadget>\n<output>276</output>\n\n<gadget id=\"calculator\">93 * 2</gadget>\n<output>186</output>\n\n<gadget id=\"calculator\">276 - 186</gadget>\n<output>90</output>\n\n<result>90</result>", "result": "90", "source": "calc"}
|
||||
{"id": "aqua_rat__r54xvzEL3O9nU60t", "question": "Barbata invests $2400 in the National Bank at 5%. How much additional money must she invest at 10% so that the total annual income will be equal to 6% of her entire investment?\nPick one:\nA) 120\nB) 600\nC) 1000\nD) 360\nE) 240", "chain": "Let the additional invested amount for 10% interest be x; Equation will be; 2400+0.05*2400+x+0.10x = 2400+x+0.06(2400+x) 0.05*2400+0.10x = 0.06x+0.06*2400 0.04x = 2400(0.06-0.05) x = 2400*0.01/0.04= \n<gadget id=\"calculator\">2400*0.01/0.04</gadget>\n<output>600</output>\n600 Ans:600\n<result>B</result>", "result": "B", "source": "calc"}
|
||||
{"id": "ape210k__00851767", "question": "There are 30 boys in the dance group, and there are fewer girls than boys (1/5). How many girls are there?", "chain": "<gadget id=\"calculator\">1 / 5</gadget>\n<output>1/5 = around 0.2</output>\n\n<gadget id=\"calculator\">1 - (1/5)</gadget>\n<output>4/5 = around 0.8</output>\n\n<gadget id=\"calculator\">30 * (4/5)</gadget>\n<output>24</output>\n\n<result>24</result>", "result": "24", "source": "calc"}
|
||||
{"id": "ape210k__00935567", "question": "Uncle Wang has 20 goats, 14 sheep, and 408 rabbits. How many times more rabbits are there than sheep?", "chain": "<gadget id=\"calculator\">20 + 14</gadget>\n<output>34</output>\n\n<gadget id=\"calculator\">408 / 34</gadget>\n<output>12</output>\n\n<result>12</result>", "result": "12", "source": "calc"}
|
||||
{"id": "math_qa__tyaZVO6Q2uEE7wBw", "question": "How much greater is the combined area in square inches of the front and back of a rectangular sheet of paper measuring 11 inches by 11 inches than that of a rectangular sheet of paper measuring 5.5 inches by 11 inches?\tChoose the correct choice from the following choices:\nA) 50 % B) 87 % C) 100 % D) 187 % E) 200 %", "chain": "<gadget id=\"calculator\">11 * 11</gadget>\n<output>121</output>\n\n<gadget id=\"calculator\">121 * 2</gadget>\n<output>242</output>\n\n<gadget id=\"calculator\">5.5 * 11</gadget>\n<output>60.5</output>\n\n<gadget id=\"calculator\">60.5 * 2</gadget>\n<output>121</output>\n\n<gadget id=\"calculator\">242 - 121</gadget>\n<output>121</output>\n\n<gadget id=\"calculator\">121 / 121</gadget>\n<output>1</output>\n\n<gadget id=\"calculator\">1 * 100</gadget>\n<output>100</output>\n\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
{"id": "aqua_rat__Qtp9RDyp7cecUmpb", "question": "0.01 is what percent of 0.1? Choices: A) 1% B) 10% C) 100% D) 50% E) 25%", "chain": "Required percentage = 0.01*100/0.1 = 100/10= \n<gadget id=\"calculator\">100/10</gadget>\n<output>10</output>\n10% Answer is 10%\n<result>B</result>", "result": "B", "source": "calc"}
|
||||
{"id": "ape210k__01121109", "question": "It is known that the sum of 9 consecutive natural numbers is 315, so what is the largest number among them.", "chain": "<gadget id=\"calculator\">315 / 9</gadget>\n<output>35</output>\n\n<gadget id=\"calculator\">35 + 1 + 1 + 1 + 1</gadget>\n<output>39</output>\n\n<result>39</result>", "result": "39", "source": "calc"}
|
||||
{"id": "aqua_rat__JwrYawp1nZkf5o7a", "question": "Josh spends a total of $5.5 buying S items in the convenience store. If each of the items is either a 5 cents single bubblegum, or a 50 cents bubblegum pack, then S may be which of the following?\nChoose the correct choice from the following answers.\nA) 99\nB) 100\nC) 101\nD) 112\nE) 113", "chain": "S items in the convenience store$5.5 = 550 cents 550 = 50a + 5b =>110 = 10a + b b = 110 - 10a = 10(11-a) Hence b is even and multiple of 10. Possible values of b: b = 10,20,30,40,50,60,70,80,90,100 a = 11,9,8,7,6,5,4,3,2,1 The total (a+b) is 21,29,38,47,56,65,74,83,92,101 The only option is 101. Hence 101.\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
{"id": "ape210k__00348953", "question": "The road repair team repaired a road, 185 meters a day. It has been repaired for 20 days, and another 128 meters will be completed. How long is this road?", "chain": "<gadget id=\"calculator\">185 * 20</gadget>\n<output>3_700</output>\n\n<gadget id=\"calculator\">3_700 + 128</gadget>\n<output>3_828</output>\n\n<result>3_828</result>", "result": "3_828", "source": "calc"}
|
||||
{"id": "ape210k__00285692", "question": "The lateral expansion of a cylinder is a square with side length 8 cm. What is the lateral area of this cylinder in cm**2.", "chain": "<gadget id=\"calculator\">8 ** 2</gadget>\n<output>64</output>\n\n<result>64</result>", "result": "64", "source": "calc"}
|
||||
{"id": "ape210k__00391316", "question": "The greatest common factor of two numbers A and B is 5, and the least common multiple is 60. Where the number of A is 15, what is the number of B?", "chain": "<gadget id=\"calculator\">4 * 5</gadget>\n<output>20</output>\n\n<result>20</result>", "result": "20", "source": "calc"}
|
||||
{"id": "aqua_rat__yG3x6Th3XteHm4gg", "question": "The probability is 1/2 that a certain coin turns up heads on any given toss. If the coin is tossed five times, what is the probability that the coin turns up tails on at least one of the tosses? Choose the most appropriate option.\nA) 7/8 B) 15/16 C) 31/32 D) 21/32 E) 31/64", "chain": "P(5 heads)= 1/2*1/2*1/2*1/2*1/2=1/32. P(at least one tail)=1-1/32=31/32. The answer is 31/32.\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
{"id": "ape210k__00459584", "question": "Xiaohua took a photo and wanted to make a wooden photo frame for the photo. The length of the photo frame is 25 cm and the width is 20 cm. At least how many centimeters of wooden strips should be prepared?", "chain": "<gadget id=\"calculator\">25 + 20</gadget>\n<output>45</output>\n\n<gadget id=\"calculator\">45 * 2</gadget>\n<output>90</output>\n\n<result>90</result>", "result": "90", "source": "calc"}
|
||||
{"id": "aqua_rat__eDeVHpDSC7yeRy8K", "question": "Two cards are drawn at random from a pack of 52 cards.what is the probability that either both are black or both are queen\nChoose the correct choice from the following\nA) 44/221\nB) 55/221\nC) 76/221\nD) 45/221\nE) 63/221", "chain": "WE HAVE N(S)=52C2=(52*51)/(2*1)= \n<gadget id=\"calculator\">(52*51)/(2*1)</gadget>\n<output>1_326</output>\n1326. LET A=EVENT OF GETTING 55/221OTH 55/221LACK CARDS 55/221=EVENT OF GETTING 55/221OTH QUEENS A\uf0c755/221=EVENT OF GETTING QUEEN OF 55/221LACK CARDS N(A)=26C2=(26*25)/(2*1)= \n<gadget id=\"calculator\">(26*25)/(2*1)</gadget>\n<output>325</output>\n325, N(55/221)=4C2=(4*3)/(2*1)= \n<gadget id=\"calculator\">(4*3)/(2*1)</gadget>\n<output>6</output>\n6 AND N(A\uf0c755/221)=2C2=1 P(A)=N(A)/N(S)=325/1326; P(55/221)=N(55/221)/N(S)=6/1326 AND P(A\uf0c755/221)=N(A\uf0c755/221)/N(S)=1/1326 P(A\uf0c855/221)=P(A)+P(55/221)-P(A\uf0c755/221)=(325+6-1/1326)=330/1326=55/221 Option: 55/221\n<result>B</result>", "result": "B", "source": "calc"}
|
||||
{"id": "aqua_rat__8P5OAZaXVQlL4d8P", "question": "If two numbers are in the ratio 2:3. If 5 is added to both of the numbers then the ratio becomes 3:4 then find the smallest number?\nAnswers: A) A)10 B) B)18 C) C)20 D) D)24 E) E)26", "chain": "2:3 2x + 5 : 3x + 5 = 3 : 4 4[2x + 5] = 3[3x + 5] 8x + 20 = 9x + 15 9x - 8x = 20 - 15= \n<gadget id=\"calculator\">20 - 15</gadget>\n<output>5</output>\n5 Then smallest number is= 2 2x = 10 Correct Option 10\n<result>A</result>", "result": "A", "source": "calc"}
|
||||
{"id": "aqua_rat__1sGqyWbPyIDgCvSg", "question": "If a, b, c, d, e and f are integers and (ab + cdef) < 0, then what is the maximum number S of integers that can be negative? Choose the correct choice from the following answers.\nA) 2 B) 3 C) 4 D) 5 E) 6", "chain": "Minimuum should be 1 Maximum should be 4: 1 out of a or b to make the multiplication negative 3 out of c, d, e or f to make the multiplication negative. Negative+Negative<0 Answer:C maximum will be 5.. you dont require both the multiplicatin to be negative for entire equation to be negative... any one a or b can be negative to make ab negative and it can still be more(away from 0) than the multiplication of 4 other -ve numbers... actually by writing minimum required as 1 out of 6,you are actually meaning S= 5 out of 6 also possible as you will see 5 or 1 will give you same equation.. ans 5\n<result>D</result>", "result": "D", "source": "calc"}
|
||||
{"id": "aqua_rat__mGakVxdUhicX5FmA", "question": "Find the area of the quadrilateral of one of its diagonals is 10 cm and its off sets 7 cm and 3 cm? Choose the correct choice from the following answers\nA) 50 cm2\tB) 100 cm2\tC) 150 cm2\tD) 200 cm2\tE) 250 cm2", "chain": "1/2 * 10(7 + 3) = 50 cm2 50 cm2nswer: 50 cm2\n<result>A</result>", "result": "A", "source": "calc"}
|
||||
{"id": "ape210k__00398657", "question": "A right-angled trapezoid has an upper base of 2 cm and a waist length of 10 cm. If the upper base is increased by 6 cm, it becomes a square. What is the perimeter of the trapezoid in cm?", "chain": "<gadget id=\"calculator\">2 + 6</gadget>\n<output>8</output>\n\n<gadget id=\"calculator\">8 * 2</gadget>\n<output>16</output>\n\n<gadget id=\"calculator\">2 + 16 + 10</gadget>\n<output>28</output>\n\n<result>28</result>", "result": "28", "source": "calc"}
|
||||
{"id": "aqua_rat__1I3XjjMFYW6ivEn6", "question": "In 1998 the profits of company N were 10 percent of revenues. In 1999, the revenues of company N fell by 20 percent, but profits were 14 percent of revenues. The profits in 1999 were what percent of the profits in 1998? Answers.\nA) 80% B) 105% C) 120% D) 112% E) 138%", "chain": "0,112R = x/100*0.1R Answer 112%\n<result>D</result>", "result": "D", "source": "calc"}
|
||||
{"id": "aqua_rat__orCiKDobdncZcRw8", "question": "In a market, a dozen eggs cost as much as a pound of rice, and a half-liter of kerosene costs as much as 6 eggs. If the cost of each pound of rice is $0.24, then how many cents does a liter of kerosene cost? [One dollar has 100 cents.]\nChoose the correct choice.\nA) 0.20 B) 0.24 C) 20 D) 24 E) 55", "chain": "A dozen eggs cost as much as a pound of rice --> 12 eggs = 1 pound of rice = 24 cents; A half-liter of kerosene costs as much as 6 eggs --> 6 eggs = 1/2 liters of kerosene. How many cents does a liter of kerosene cost --> 1 liter of kerosene = 12 eggs = 12/12*24= \n<gadget id=\"calculator\">12/12*24</gadget>\n<output>24</output>\n24 cents. Answer: 24.\n<result>D</result>", "result": "D", "source": "calc"}
|
||||
{"id": "ape210k__00022661", "question": "A company saved an average of 9 tons of water per day in the second quarter of last year. How many tons of water was saved in the second quarter?", "chain": "<gadget id=\"calculator\">30 + 31 + 30</gadget>\n<output>91</output>\n\n<gadget id=\"calculator\">91 * 9</gadget>\n<output>819</output>\n\n<result>819</result>", "result": "819", "source": "calc"}
|
||||
{"id": "ape210k__00154447", "question": "(2/10) meters are used up for a piece of iron wire, and (8/10) meters are left, what is the original length of this iron wire", "chain": "<gadget id=\"calculator\">2 / 10</gadget>\n<output>1/5 = around 0.2</output>\n\n<gadget id=\"calculator\">8 / 10</gadget>\n<output>4/5 = around 0.8</output>\n\n<gadget id=\"calculator\">(1/5) + (4/5)</gadget>\n<output>1</output>\n\n<result>1</result>", "result": "1", "source": "calc"}
|
||||
{"id": "ape210k__00461545", "question": "Subtract 8 continuously from 496, and it will be 0 after how many times of subtraction.", "chain": "<gadget id=\"calculator\">496 / 8</gadget>\n<output>62</output>\n\n<result>62</result>", "result": "62", "source": "calc"}
|
||||
{"id": "ape210k__00220514", "question": "There are 54 cards in a deck of poker, ask: at least how many cards can be drawn from it to ensure that there are cards of four suits.", "chain": "<gadget id=\"calculator\">13 * 3</gadget>\n<output>39</output>\n\n<gadget id=\"calculator\">39 + 2 + 1</gadget>\n<output>42</output>\n\n<result>42</result>", "result": "42", "source": "calc"}
|
||||
{"id": "ape210k__00832821", "question": "There are several small balls of 4 different colors in the cloth bag, and the minimum number of small balls taken out can ensure that there must be 2 small balls of the same color.", "chain": "<gadget id=\"calculator\">4 + 1</gadget>\n<output>5</output>\n\n<result>5</result>", "result": "5", "source": "calc"}
|
||||
{"id": "ape210k__01121969", "question": "The fruit shop shipped 28 boxes of apples and pears each, each weighing 30 kg for pears and 25 kg for apples. How many kilograms of fruit does the fruit shop ship? (calculated in two ways)", "chain": "<gadget id=\"calculator\">28 * 30</gadget>\n<output>840</output>\n\n<gadget id=\"calculator\">28 * 25</gadget>\n<output>700</output>\n\n<gadget id=\"calculator\">840 + 700</gadget>\n<output>1_540</output>\n\n<result>1_540</result>", "result": "1_540", "source": "calc"}
|
||||
{"id": "ape210k__00910759", "question": "For a children's bicycle, the gear ratio of the front and rear gears is 12:7. If the rear gear rotates 24 times, how many times does the front gear rotate?", "chain": "<gadget id=\"calculator\">7 * 24</gadget>\n<output>168</output>\n\n<gadget id=\"calculator\">168 / 12</gadget>\n<output>14</output>\n\n<result>14</result>", "result": "14", "source": "calc"}
|
||||
{"id": "ape210k__01067071", "question": "If there is a basket of apples distributed among 6 people on average, there are 3 apples left. How many apples are there in this basket?", "chain": "<gadget id=\"calculator\">5 * 2 * 3</gadget>\n<output>30</output>\n\n<gadget id=\"calculator\">30 + 3</gadget>\n<output>33</output>\n\n<result>33</result>", "result": "33", "source": "calc"}
|
||||
{"id": "math_qa__nn3MNd29MSEsMQhG", "question": "Income and expenditure of a person are in the ratio 9 : 8. If the income of the person is Rs. 18000, then find his savings?\tChoose the correct choice:\nA) rs . 3600\nB) rs . 3603\nC) rs . 2000\nD) rs . 3632\nE) rs . 3602", "chain": "<gadget id=\"calculator\">8 / 9</gadget>\n<output>8/9 = around 0.888889</output>\n\n<gadget id=\"calculator\">(8/9) * 18_000</gadget>\n<output>16_000</output>\n\n<gadget id=\"calculator\">18_000 - 16_000</gadget>\n<output>2_000</output>\n\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
{"id": "aqua_rat__ALWjr7wktcHDeMLJ", "question": "Twelve contestants at the county fair have entered their cakes to be judged in the cake decorating competition. A purple ribbon, blue ribbon, red ribbon, and white ribbon will be given to the first, second, third, and fourth place competitors, respectively. How many different ways are there to award the four ribbons to the contestants?\tAnswers\nA) 8!(4!*4!)\nB) 12!(8!*4!)\nC) 8!/4!\nD) 12!/8!\nE) 12!/4!", "chain": "The mistake you are doing is that you are neglecting the 4! ways in you can arrange 4 contestants for the 4 prizes. Number of ways you can select 4 people out of 12 = 12C4 Once you select the 4 people, you have the following arrangement, PBRW (PBRW being the 4 prizes) but the same group of people can also be chosen against BRWP etc. Thus you get 4! ways of arranging 4 prizes. Thus total possible ways = 12C4*4! = 12!/8!. 12!/8! is the correct answer.\n<result>D</result>", "result": "D", "source": "calc"}
|
||||
{"id": "ape210k__00947619", "question": "The material for the jacket is 1.55 meters per piece, and the material for the trousers is 1.05 meters per piece. How much rice cloth is needed to make a jacket and two trousers?", "chain": "<gadget id=\"calculator\">1.05 * 2</gadget>\n<output>2.1</output>\n\n<gadget id=\"calculator\">2.1 + 1.55</gadget>\n<output>3.65</output>\n\n<result>3.65</result>", "result": "3.65", "source": "calc"}
|
||||
{"id": "aqua_rat__cJf6UOtVHqOWRGHY", "question": "If m and n are positive integers of T such that m is a factor of n, how many positive multiples of m are less than or equal to 2n ?\tAnswers.\nA) 2m/n + 1 B) 2n/m + 1 C) 2n/(m+1) D) 2m/n E) 2n/m", "chain": "Lets say N=10, M=5 2N=20. so the answer should be 4 (20/5) lets try to plug in the answers: A-not an integer B-not an integer C-not an integer D-1 (not the answer) E-4 - the answer. (the only one). I would choose E. Method 2 N=M*A (A is an integer) So - A=N/M therefore in 2N A will be 2N/M Again - Answer is 2n/m.\n<result>E</result>", "result": "E", "source": "calc"}
|
||||
{"id": "ape210k__00628803", "question": "The fruit shop shipped 450 kilograms of papaya, of which Taiwan papaya accounted for (2/9), how many kilograms of Taiwan papaya?", "chain": "<gadget id=\"calculator\">2 / 9</gadget>\n<output>2/9 = around 0.222222</output>\n\n<gadget id=\"calculator\">450 * (2/9)</gadget>\n<output>100</output>\n\n<result>100</result>", "result": "100", "source": "calc"}
|
||||
{"id": "ape210k__00708383", "question": "If the radius of a circle is 1 cm, what is the circumference of its semicircle in cm?", "chain": "<gadget id=\"calculator\">1 / 2</gadget>\n<output>1/2 = around 0.5</output>\n\n<gadget id=\"calculator\">2 * 3.14 * (1/2)</gadget>\n<output>3.14</output>\n\n<gadget id=\"calculator\">2 * 1</gadget>\n<output>2</output>\n\n<gadget id=\"calculator\">3.14 + 2</gadget>\n<output>5.14</output>\n\n<result>5.14</result>", "result": "5.14", "source": "calc"}
|
||||
{"id": "ape210k__00256542", "question": "(1/(1*3))+(1/(3*5))+(1/(5*7))+...(1/(47*49)).", "chain": "<gadget id=\"calculator\">1 / 49</gadget>\n<output>1/49 = around 0.020408</output>\n\n<gadget id=\"calculator\">1 - (1/49)</gadget>\n<output>48/49 = around 0.979592</output>\n\n<gadget id=\"calculator\">1 / 2</gadget>\n<output>1/2 = around 0.5</output>\n\n<gadget id=\"calculator\">(48/49) * (1/2)</gadget>\n<output>24/49 = around 0.489796</output>\n\n<result>24/49 = around 0.489796</result>", "result": "24/49", "source": "calc"}
|
||||
{"id": "ape210k__00046559", "question": "An oil barrel is filled with half a barrel of oil, and after pouring out (3/5) of the oil, there is still 8 kilograms of oil left. How many kilograms of oil can this oil barrel hold?", "chain": "<gadget id=\"calculator\">3 / 5</gadget>\n<output>3/5 = around 0.6</output>\n\n<gadget id=\"calculator\">1 - (3/5)</gadget>\n<output>2/5 = around 0.4</output>\n\n<gadget id=\"calculator\">8 / (2/5)</gadget>\n<output>20</output>\n\n<gadget id=\"calculator\">20 * 2</gadget>\n<output>40</output>\n\n<result>40</result>", "result": "40", "source": "calc"}
|
||||
{"id": "ape210k__00838787", "question": "cuboid plastic box containing liquid medicine has a length of 0.6 meters, a width of 0.25 meters, and a depth of 0.5 meters. If the whole box of medicines is packed into small bottles that can hold 400 milliliters, how many bottles should this box contain at least?", "chain": "<gadget id=\"calculator\">100 / 400</gadget>\n<output>1/4 = around 0.25</output>\n\n<gadget id=\"calculator\">0.6 * 100 * 0.25 * 100 * 0.5 * (1/4) * 10</gadget>\n<output>1_875</output>\n\n<result>1_875</result>", "result": "1_875", "source": "calc"}
|
||||
{"id": "ape210k__01031589", "question": "Stack 2,100 cubes with side lengths of 1 cm to form a solid cuboid. Its height is 10 cm, and its length and width are greater than its height. What is the sum of the length and width of this cuboid in cm?", "chain": "<gadget id=\"calculator\">15 + 14</gadget>\n<output>29</output>\n\n<result>29</result>", "result": "29", "source": "calc"}
|
||||
{"id": "aqua_rat__7f9Pgjdk9qlo5Tf9", "question": "If the product 4864*9 P 2 is divisible by 12, the value of p?\nOptions\nA) 1 B) 5 C) 6 D) 7 E) 9", "chain": "Explanation: clearly 4864 is divisible by 4 So 9 P 2 must be divisible by 3.So(9+P+2) must be divisible by 3. so P=1. 1nswer: 1) 1\n<result>A</result>", "result": "A", "source": "calc"}
|
||||
{"id": "ape210k__00563400", "question": "It is known that \u22201+\u22202=150\u00b0, \u22201=67\u00b0, then \u22202=how much.", "chain": "<gadget id=\"calculator\">150 - 67</gadget>\n<output>83</output>\n\n<result>83</result>", "result": "83", "source": "calc"}
|
||||
{"id": "ape210k__00850129", "question": "The weight of an astronaut on the earth is 72 kg, which is 6 times his weight on the moon. How many kilograms would he weigh on the moon?", "chain": "<gadget id=\"calculator\">72 / 6</gadget>\n<output>12</output>\n\n<result>12</result>", "result": "12", "source": "calc"}
|
||||
{"id": "ape210k__00838563", "question": "In a bag of sugar, toffee accounts for 25% of the total number. After putting in 20 pieces of fruit candy, toffee accounts for 20% of the total number. How many pieces of toffee are there?", "chain": "<gadget id=\"calculator\">25 / 100</gadget>\n<output>1/4 = around 0.25</output>\n\n<gadget id=\"calculator\">80 * (1/4)</gadget>\n<output>20</output>\n\n<result>20</result>", "result": "20", "source": "calc"}
|
||||
{"id": "ape210k__00921605", "question": "To process a batch of parts, A alone can complete it in 9 days, and B alone can complete it in 12 days.", "chain": "<gadget id=\"calculator\">1 / 9</gadget>\n<output>1/9 = around 0.111111</output>\n\n<gadget id=\"calculator\">1 / 12</gadget>\n<output>1/12 = around 0.083333</output>\n\n<gadget id=\"calculator\">(1/9) + (1/12)</gadget>\n<output>7/36 = around 0.194444</output>\n\n<gadget id=\"calculator\">1 / (7/36)</gadget>\n<output>36/7 = around 5.142857</output>\n\n<result>36/7 = around 5.142857</result>", "result": "36/7", "source": "calc"}
|
||||
{"id": "ape210k__01057303", "question": "A batch of coal is shipped from the boiler room of a certain factory. According to the daily consumption of 150 kg of coal in the old boiler, it can be used for 120 days. If a new boiler is used, the coal consumption will be reduced by 20%. How many more days can this batch of coal be burned?", "chain": "<gadget id=\"calculator\">20 / 100</gadget>\n<output>1/5 = around 0.2</output>\n\n<gadget id=\"calculator\">1 - (1/5)</gadget>\n<output>4/5 = around 0.8</output>\n\n<gadget id=\"calculator\">150 * (4/5)</gadget>\n<output>120</output>\n\n<gadget id=\"calculator\">120 / 120</gadget>\n<output>1</output>\n\n<gadget id=\"calculator\">150 * 1</gadget>\n<output>150</output>\n\n<gadget id=\"calculator\">150 - 120</gadget>\n<output>30</output>\n\n<result>30</result>", "result": "30", "source": "calc"}
|
||||
{"id": "ape210k__00442282", "question": "Dissolve 1 gram of sugar in 10 grams of water, how much sugar accounts for the sugar water", "chain": "<gadget id=\"calculator\">1 + 10</gadget>\n<output>11</output>\n\n<gadget id=\"calculator\">1 / 11</gadget>\n<output>1/11 = around 0.090909</output>\n\n<result>1/11 = around 0.090909</result>", "result": "1/11", "source": "calc"}
|
||||
{"id": "ape210k__00030668", "question": "In the final exam, Dalang's average score in the four subjects was 90 before the English score was announced. After the English score was announced, his average score increased by 2 points. How many points did Dawa score in the English test?", "chain": "<gadget id=\"calculator\">90 + 2</gadget>\n<output>92</output>\n\n<gadget id=\"calculator\">92 * 5</gadget>\n<output>460</output>\n\n<gadget id=\"calculator\">90 * 4</gadget>\n<output>360</output>\n\n<gadget id=\"calculator\">460 - 360</gadget>\n<output>100</output>\n\n<result>100</result>", "result": "100", "source": "calc"}
|
||||
{"id": "ape210k__00295527", "question": "A project has been completed (2/3) by 8 workers in 24 days, and it needs to be completed in 28 days. (Continue to work) How many more people are needed?", "chain": "<gadget id=\"calculator\">2 / 3</gadget>\n<output>2/3 = around 0.666667</output>\n\n<gadget id=\"calculator\">1 - (2/3)</gadget>\n<output>1/3 = around 0.333333</output>\n\n<gadget id=\"calculator\">(2/3) / 8 / 24</gadget>\n<output>1/288 = around 0.003472</output>\n\n<gadget id=\"calculator\">28 - 24</gadget>\n<output>4</output>\n\n<gadget id=\"calculator\">(1/288) * 4</gadget>\n<output>1/72 = around 0.013889</output>\n\n<gadget id=\"calculator\">(1/3) / (1/72)</gadget>\n<output>24</output>\n\n<gadget id=\"calculator\">24 - 8</gadget>\n<output>16</output>\n\n<result>16</result>", "result": "16", "source": "calc"}
|
||||
{"id": "aqua_rat__tasT86j2f4Cpn4kL", "question": "750 students took the test on English and Maths. 35% students failed in english and 45% failed in maths. 40% of those who passed in maths also passed in english, then how many students failed in both ? Choose the correct choice:\nA) a) 162\nB) b) 15\nC) c) 60\nD) d) 38\nE) e) 12", "chain": "Passed in english = 65% Passed in maths = 55% Passed in both = 40% of 55% = 2/5 * (55%) = 22% Passed in (English + Maths - b) 15oth + Neither) 2/5 * (55 )= \n<gadget id=\"calculator\">2/5 * (55 )</gadget>\n<output>22</output>\n22% Passed in (English + Maths - b) 15oth + Neither)= 100% 65 + 55 - 22 + Neither = 100 Neither = 100 - 98= \n<gadget id=\"calculator\">100 - 98</gadget>\n<output>2</output>\n2%= 0.02 * 750= \n<gadget id=\"calculator\">0.02 * 750</gadget>\n<output>15</output>\n15 Answer: b) 15\n<result>B</result>", "result": "B", "source": "calc"}
|
||||
{"id": "aqua_rat__OeZ7ZLBAPlOfp6Wg", "question": "A batsman scored 130 runs which included 3 boundaries and 8 sixes. What percent of his total score did he make by running between the wickets? Choose the correct choice from the following answers.\nA) 45(4/11) % B) 45 % C) 53(11/13) % D) 44(5/11) % E) None of these", "chain": "Explanation : Total runs scored = 130 Total runs scored from boundaries and sixes = 3 x 4 + 8 x 6 = 60 Total runs scored by running between the wickets = 130 - 60= \n<gadget id=\"calculator\">130 - 60</gadget>\n<output>70</output>\n70 Required %= (70/130) \u00d7 100 = 700/13 = 53(11/13)% Answer : Option 53(11/13) %\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
{"id": "ape210k__00084943", "question": "(19/20) minus (13/20), and how much to subtract, the difference is (1/5).", "chain": "<gadget id=\"calculator\">19 / 20</gadget>\n<output>19/20 = around 0.95</output>\n\n<gadget id=\"calculator\">13 / 20</gadget>\n<output>13/20 = around 0.65</output>\n\n<gadget id=\"calculator\">1 / 5</gadget>\n<output>1/5 = around 0.2</output>\n\n<gadget id=\"calculator\">(19/20) - (13/20) - (1/5)</gadget>\n<output>1/10 = around 0.1</output>\n\n<result>1/10 = around 0.1</result>", "result": "1/10", "source": "calc"}
|
||||
{"id": "ape210k__00010503", "question": "Add 8 trees equidistantly between the two trees, so that the distance between the first tree and the fifth tree is 20 meters, how many meters are the distance between the original two trees?", "chain": "<gadget id=\"calculator\">5 - 1</gadget>\n<output>4</output>\n\n<gadget id=\"calculator\">20 / 4</gadget>\n<output>5</output>\n\n<gadget id=\"calculator\">8 + 1</gadget>\n<output>9</output>\n\n<gadget id=\"calculator\">5 * 9</gadget>\n<output>45</output>\n\n<result>45</result>", "result": "45", "source": "calc"}
|
||||
{"id": "ape210k__00468021", "question": "A 2-meter-long iron wire uses up 4 decimeters, and the rest forms a square. What is the side length of the enclosed square?", "chain": "<gadget id=\"calculator\">2 * 10</gadget>\n<output>20</output>\n\n<gadget id=\"calculator\">20 - 4</gadget>\n<output>16</output>\n\n<gadget id=\"calculator\">16 / 4</gadget>\n<output>4</output>\n\n<result>4</result>", "result": "4", "source": "calc"}
|
||||
{"id": "ape210k__00041697", "question": "There is a rectangular vegetable field with a length of 35 meters and a width of 14 meters. What is the area of this vegetable field in square meters?", "chain": "<gadget id=\"calculator\">35 * 14</gadget>\n<output>490</output>\n\n<result>490</result>", "result": "490", "source": "calc"}
|
||||
{"id": "aqua_rat__sr81Rp7oIv2lWfLl", "question": "Rectangular tile each of size 80cm by 40cm must be laid horizontally on a rectangular floor of size 130cm by 230cm,such that the tiles do not overlap and they are placed with edges jutting against each other on all edges. A tile can be placed in any orientation so long as its edges are parallel to the edges of floor. No tile should overshoot any edge of the floor. The maximum number of tiles that can be accommodated on the floor is: Choose the correct option:\nA) 6\tB) 2\tC) 8\tD) 9\tE) 7", "chain": "Area of tile = 80*40= \n<gadget id=\"calculator\">80*40</gadget>\n<output>3_200</output>\n3200 Area of floor= 130*230= \n<gadget id=\"calculator\">130*230</gadget>\n<output>29_900</output>\n29900 No of tiles= 29900/3200 = 9.34 So, the no of tile = 9 ANSWER:9\n<result>D</result>", "result": "D", "source": "calc"}
|
||||
{"id": "ape210k__00607118", "question": "Xiaoxiao scored 92 in Chinese, 98 in mathematics, and 95 in English in the final test. What is her average score in the three subjects?", "chain": "<gadget id=\"calculator\">92 + 98 + 95</gadget>\n<output>285</output>\n\n<gadget id=\"calculator\">285 / 3</gadget>\n<output>95</output>\n\n<result>95</result>", "result": "95", "source": "calc"}
|
||||
{"id": "ape210k__00940095", "question": "The fruit store shipped 425 kilograms of apples, and the pears shipped were 80 kilograms less than four times the apples. How many kilograms of pears did the fruit store ship?", "chain": "<gadget id=\"calculator\">425 * 4</gadget>\n<output>1_700</output>\n\n<gadget id=\"calculator\">1_700 - 80</gadget>\n<output>1_620</output>\n\n<result>1_620</result>", "result": "1_620", "source": "calc"}
|
||||
{"id": "ape210k__00428406", "question": "If a cuboid has a base area of 80 cm2 and a height of 7 cm, what is its volume in cubic cm?", "chain": "<gadget id=\"calculator\">80 * 7</gadget>\n<output>560</output>\n\n<result>560</result>", "result": "560", "source": "calc"}
|
||||
{"id": "math_qa__Oc10lU6MVDif6R2Q", "question": "Matt and Peter can do together a piece of work in 20 days. After they have worked together for 12 days Matt stops and Peter completes the remaining work in 8 days. In how many days Peter complete the work separately.\nChoices:\nA) 21\nB) 24\nC) 20\nD) 25\nE) 30", "chain": "<gadget id=\"calculator\">1 / 20</gadget>\n<output>1/20 = around 0.05</output>\n\n<gadget id=\"calculator\">12 * (1/20)</gadget>\n<output>3/5 = around 0.6</output>\n\n<gadget id=\"calculator\">1 - (3/5)</gadget>\n<output>2/5 = around 0.4</output>\n\n<gadget id=\"calculator\">8 / (2/5)</gadget>\n<output>20</output>\n\n<result>C</result>", "result": "C", "source": "calc"}
|
||||
@@ -0,0 +1,338 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""This sample demonstrates the basic usage pattern of agent-framework-lab-lightning.
|
||||
|
||||
It trains a math agent using a dataset in `data/math/` to solve mathematical problems
|
||||
using an MCP calculator tool.
|
||||
|
||||
One GPU with 40GB of memory is sufficient for this sample.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
from typing import TypedDict, cast
|
||||
|
||||
import sympy # type: ignore[import-untyped,reportMissingImports]
|
||||
from agent_framework._agents import ChatAgent
|
||||
from agent_framework._mcp import MCPStdioTool
|
||||
from agent_framework._types import AgentRunResponse
|
||||
from agent_framework.openai._chat_client import OpenAIChatClient
|
||||
from agent_framework_lab_lightning import init as lightning_init
|
||||
from agentlightning import LLM, Dataset, Trainer, rollout
|
||||
from agentlightning.algorithm.verl import VERL
|
||||
|
||||
|
||||
class MathProblem(TypedDict):
|
||||
"""This TypedDict defines the structure of each training sample.
|
||||
|
||||
Your task structure should contain all the information needed for:
|
||||
|
||||
- The agent to process the task (e.g., 'question')
|
||||
- Evaluation (e.g., 'result' for ground truth)
|
||||
|
||||
This type is optional. Not necessary to make the example work.
|
||||
"""
|
||||
|
||||
# The fields come from the dataset
|
||||
id: str
|
||||
question: str # The math problem for the agent to solve
|
||||
chain: str # Step-by-step solution (not used in training)
|
||||
result: str # Ground truth answer for evaluation
|
||||
source: str
|
||||
|
||||
|
||||
def _load_jsonl(file_path: str) -> Dataset[MathProblem]:
|
||||
"""Load your dataset as a list of task samples.
|
||||
|
||||
Each sample should match your task structure (MathProblem in this case).
|
||||
"""
|
||||
with open(file_path) as f:
|
||||
raw_data = [MathProblem(**json.loads(line)) for line in f]
|
||||
return cast(Dataset[MathProblem], raw_data)
|
||||
|
||||
|
||||
# Evaluation logic
|
||||
# These functions evaluate whether the agent's answer matches the ground truth.
|
||||
# Robust evaluation is crucial for RL training - the reward signal guides learning.
|
||||
|
||||
|
||||
def _normalize_option(option: str) -> str:
|
||||
return re.sub(r"(\s+|\(|\))", "", option)
|
||||
|
||||
|
||||
def _is_option_result(result: str) -> bool:
|
||||
return _normalize_option(result) in list(string.ascii_letters)
|
||||
|
||||
|
||||
def _float_eval(input_str: str) -> float:
|
||||
if " = around " in input_str:
|
||||
input_str = input_str.split(" = around ")[0]
|
||||
expr = sympy.parse_expr(input_str, evaluate=True)
|
||||
return float(expr.evalf())
|
||||
|
||||
|
||||
def _scalar_are_results_same(pred_result: str, true_result: str, rel_tol: float) -> bool:
|
||||
pred_result = str(pred_result) if pred_result is not None else ""
|
||||
true_result = str(true_result) if true_result is not None else ""
|
||||
|
||||
if pred_result.strip() == true_result.strip():
|
||||
return True
|
||||
|
||||
if _is_option_result(true_result):
|
||||
# The task is to select correct option
|
||||
true_result = _normalize_option(true_result)
|
||||
pred_result = _normalize_option(pred_result)
|
||||
return pred_result == true_result
|
||||
|
||||
# The task is to calculate the result as a number
|
||||
try:
|
||||
pred_float = _float_eval(pred_result)
|
||||
true_float = _float_eval(true_result)
|
||||
return math.isclose(pred_float, true_float, rel_tol=rel_tol)
|
||||
except Exception: # noqa: S110
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _is_result_correct(prediction: str, ground_truth: str) -> float:
|
||||
return float(_scalar_are_results_same(prediction, ground_truth, 1e-2))
|
||||
|
||||
|
||||
def evaluate(result: AgentRunResponse, ground_truth: str) -> float:
|
||||
"""Main evaluation function that extracts the agent's answer and compares with ground truth.
|
||||
|
||||
This function:
|
||||
1. Extracts the final answer from the agent's response (after ###)
|
||||
2. Compares it with the ground truth using mathematical equivalence
|
||||
3. Returns a reward score (0.0 or 1.0) for RL training
|
||||
|
||||
The reward signal is critical - it directly influences what the model learns.
|
||||
"""
|
||||
# Check if agent provided any response
|
||||
if len(result.messages) == 0:
|
||||
print("No response from agent. Assuming incorrect.")
|
||||
return 0.0
|
||||
final_message = result.messages[-1].text
|
||||
|
||||
# Extract answer after ### marker (as specified in agent instructions)
|
||||
answer = re.search(r"###\s*(.+?)(\s*###|$)", final_message)
|
||||
if answer is None:
|
||||
print("No answer can be extracted from agent's response. Assuming incorrect.")
|
||||
return 0.0
|
||||
answer = answer.group(1)
|
||||
|
||||
# Compare extracted answer with ground truth
|
||||
reward = _is_result_correct(answer, ground_truth)
|
||||
print(f"Reward: {reward}")
|
||||
return reward
|
||||
|
||||
|
||||
# Agent Logic
|
||||
|
||||
# Clear instructions are important for consistent agent behavior
|
||||
# The ### format helps with reliable answer extraction during evaluation
|
||||
AGENT_INSTRUCTION = """
|
||||
Solve the following math problem. Use the calculator tool to help you calculate math expressions.
|
||||
|
||||
Output the answer when you are ready. The answer should be after three sharps (`###`), with no extra punctuations or texts. For example: ### 123
|
||||
""".strip() # noqa: E501
|
||||
|
||||
|
||||
# The @rollout decorator is the key integration point with agent-lightning.
|
||||
# It tells the training system that this function defines a trainable agent.
|
||||
@rollout
|
||||
async def math_agent(task: MathProblem, llm: LLM) -> float:
|
||||
"""This is your trainable agent function.
|
||||
|
||||
Key points:
|
||||
|
||||
1. Must be decorated with @rollout
|
||||
2. Takes a task sample and LLM object as parameters
|
||||
3. Returns a float reward score (0.0 to 1.0 typically)
|
||||
4. The LLM object contains the model being trained and its configuration
|
||||
|
||||
During training:
|
||||
- llm.model: The model checkpoint being trained
|
||||
- llm.endpoint: vLLM server endpoint for inference
|
||||
- llm.sampling_parameters: Temperature, etc.
|
||||
"""
|
||||
# Create the Agent Framework components
|
||||
# MCPStdioTool provides calculator functionality via MCP protocol
|
||||
async with (
|
||||
MCPStdioTool(name="calculator", command="uvx", args=["mcp-server-calculator"]) as mcp_server,
|
||||
ChatAgent(
|
||||
chat_client=OpenAIChatClient(
|
||||
ai_model_id=llm.model, # This is the model being trained
|
||||
api_key=os.getenv("OPENAI_API_KEY") or "dummy", # Can be dummy when connecting to training LLM
|
||||
base_url=llm.endpoint, # vLLM server endpoint provided by agent-lightning
|
||||
),
|
||||
name="MathAgent",
|
||||
instructions=AGENT_INSTRUCTION,
|
||||
temperature=llm.sampling_parameters.get("temperature", 0.0),
|
||||
) as agent,
|
||||
):
|
||||
print(f"Task: {task['question'][:10]}...")
|
||||
# Run the agent on the task
|
||||
result = await agent.run(task["question"], tools=mcp_server)
|
||||
print(f"Agent responses: {result}")
|
||||
|
||||
# Evaluate and return reward - this is what drives RL training
|
||||
return evaluate(result, task["result"])
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entrypoint."""
|
||||
# Configure RL training
|
||||
# This configuration controls all aspects of the RL training process.
|
||||
# Key sections: algorithm, data, rollout, actor, trainer
|
||||
rl_training_config = {
|
||||
"agentlightning": {
|
||||
# The port to communicate between the rollout workers and the RL training process
|
||||
"port": 9999,
|
||||
},
|
||||
"algorithm": {
|
||||
# Advantage estimator type: "gae", "grpo", "reinforce_plus_plus", etc.
|
||||
"adv_estimator": "grpo"
|
||||
},
|
||||
"data": {
|
||||
# Uses this many tasks from the dataset to perform rollouts
|
||||
"train_batch_size": 8,
|
||||
# Used to filter out the over-long prompt-response pairs
|
||||
"max_prompt_length": 4096,
|
||||
"max_response_length": 1024,
|
||||
},
|
||||
"actor_rollout_ref": {
|
||||
# Controls the rollout process
|
||||
"rollout": {
|
||||
# Set to 1 unless you want to use TP in multiple GPUs
|
||||
"tensor_model_parallel_size": 1,
|
||||
# Repeat each task N many times. Required by G(rouped)RPO
|
||||
"n": 4,
|
||||
# Controls the batch size per GPU when computing the log-prob
|
||||
"log_prob_micro_batch_size_per_gpu": 2,
|
||||
# Controls the multi-turn format (this is binded to the LLM used)
|
||||
# See https://docs.vllm.ai/en/stable/features/tool_calling.html
|
||||
"multi_turn": {"format": "hermes"},
|
||||
# Only vllm is supported for now
|
||||
"name": "vllm",
|
||||
# Controls the GPU memory utilization of vLLM
|
||||
# You might want to set this to under 0.8 to prevent OOM
|
||||
"gpu_memory_utilization": 0.7,
|
||||
},
|
||||
"actor": {
|
||||
# Split each sample into sub-batches of this size for PPO
|
||||
"ppo_mini_batch_size": 8,
|
||||
# Local per-GPU micro batch size
|
||||
"ppo_micro_batch_size_per_gpu": 2,
|
||||
# Optimizer configuration
|
||||
"optim": {"lr": 1e-6},
|
||||
# Whether to use KL loss during training
|
||||
"use_kl_loss": False,
|
||||
# PPO clipping ratios for policy updates
|
||||
"clip_ratio_low": 0.2,
|
||||
"clip_ratio_high": 0.3,
|
||||
# FSDP (Fully Sharded Data Parallel) configuration for memory efficiency
|
||||
# Useful when you don't have enough GPU memory
|
||||
"fsdp_config": {
|
||||
# Whether to offload parameters to CPU
|
||||
"param_offload": True,
|
||||
# Whether to offload optimizer state to CPU
|
||||
"optimizer_offload": True,
|
||||
},
|
||||
},
|
||||
# Reference model config
|
||||
"ref": {
|
||||
# Controls the batch size per GPU when computing log-prob for reference model
|
||||
"log_prob_micro_batch_size_per_gpu": 2,
|
||||
"fsdp_config": {"param_offload": True},
|
||||
},
|
||||
# Common configs for the model
|
||||
"model": {
|
||||
# Huggingface model path.
|
||||
# If you want to train a different model, change the path here.
|
||||
"path": "Qwen/Qwen2.5-1.5B-Instruct",
|
||||
# Whether to remove padding tokens in inputs during training
|
||||
"use_remove_padding": True,
|
||||
# Enable gradient checkpointing for memory efficiency
|
||||
"enable_gradient_checkpointing": True,
|
||||
},
|
||||
},
|
||||
# Config for the trainer
|
||||
"trainer": {
|
||||
# Number of GPUs per node
|
||||
"n_gpus_per_node": 1,
|
||||
# Whether to run validation before training begins
|
||||
"val_before_train": True,
|
||||
# Logging backends to use: "console", "wandb", etc.
|
||||
"logger": ["console"],
|
||||
# Number of nodes used in the training
|
||||
"nnodes": 1,
|
||||
# Validation frequency (in training iterations)
|
||||
"test_freq": 4,
|
||||
# Number of epochs in training
|
||||
"total_epochs": 2,
|
||||
},
|
||||
}
|
||||
|
||||
# Initialize and run training
|
||||
# lightning_init() enables observability integration with agent-framework
|
||||
lightning_init()
|
||||
|
||||
# Load your datasets
|
||||
train_dataset = _load_jsonl("data/math/train.jsonl")
|
||||
val_dataset = _load_jsonl("data/math/test.jsonl")
|
||||
|
||||
# Preview the data to ensure it's loaded correctly
|
||||
print("First 5 rows of train dataset:")
|
||||
for i in range(5):
|
||||
print(train_dataset[i])
|
||||
print("First 5 rows of val dataset:")
|
||||
for i in range(5):
|
||||
print(val_dataset[i])
|
||||
|
||||
# Create trainer with VERL algorithm and start training
|
||||
# n_workers: Number of rollout workers (processes) for parallel data collection
|
||||
trainer = Trainer(algorithm=VERL(rl_training_config), n_workers=2)
|
||||
|
||||
# This starts the actual RL training loop:
|
||||
# 1. Collect rollouts using current model
|
||||
# 2. Compute advantages and train the model
|
||||
# 3. Repeat for specified number of epochs
|
||||
trainer.fit(math_agent, train_dataset, val_data=val_dataset)
|
||||
|
||||
|
||||
def debug():
|
||||
"""Debug mode allows you to test your agent function before training.
|
||||
|
||||
Always run debug mode first before starting expensive RL training!
|
||||
"""
|
||||
train_dataset = _load_jsonl("data/math/train.jsonl")
|
||||
train_sample = train_dataset[0]
|
||||
|
||||
# Use a known good model for debugging (not the one being trained)
|
||||
model = "gpt-4o-mini"
|
||||
base_url = os.getenv("OPENAI_BASE_URL")
|
||||
api_key = os.getenv("OPENAI_API_KEY")
|
||||
if api_key is None:
|
||||
raise ValueError("OPENAI_API_KEY must be set")
|
||||
if base_url is None:
|
||||
raise ValueError("OPENAI_BASE_URL must be set")
|
||||
|
||||
# Test your agent function with a sample task
|
||||
asyncio.run(math_agent(train_sample, LLM(model=model, endpoint=base_url))) # type: ignore
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--debug", action="store_true")
|
||||
args = parser.parse_args()
|
||||
if args.debug:
|
||||
debug()
|
||||
else:
|
||||
main()
|
||||
@@ -0,0 +1,233 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""Advanced example showing multi-agent RL training using Tau2 benchmark.
|
||||
|
||||
This demonstrates:
|
||||
- LitAgent class-based approach (vs @rollout decorator)
|
||||
- Multi-agent scenarios with agent filtering
|
||||
- Resource management for complex setups
|
||||
- Integration with external benchmarks
|
||||
|
||||
Builds on concepts from train_math_agent.py with additional complexity.
|
||||
Requires one GPU of at least 80GB of memory.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
from typing import TypedDict, cast
|
||||
|
||||
from agent_framework.lab.tau2 import ASSISTANT_AGENT_ID, patch_env_set_state # type: ignore
|
||||
from agent_framework.lab.tau2 import TaskRunner as Tau2TaskRunner # type: ignore
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from agent_framework_lab_lightning import init as lightning_init
|
||||
from agentlightning import LLM, Dataset, LitAgent, NamedResources, Rollout, Trainer
|
||||
from agentlightning.algorithm.verl import VERL
|
||||
from tau2.data_model.tasks import Task as Tau2Task # type: ignore[import-untyped]
|
||||
|
||||
|
||||
# Tau2 tasks are complex objects that need special handling during distributed training
|
||||
class SerializedTask(TypedDict):
|
||||
"""Tau2 task object type."""
|
||||
|
||||
id: str
|
||||
data: str # JSON-serialized task data to prevent HuggingFace conversion issues
|
||||
|
||||
|
||||
def _load_dataset() -> tuple[Dataset[SerializedTask], Dataset[SerializedTask]]:
|
||||
"""Load and prepare Tau2 dataset with proper serialization.
|
||||
|
||||
It takes external data dependency (TAU2_DATA_DIR) and uses deterministic train/val split for reproducibility.
|
||||
"""
|
||||
data_dir = os.getenv("TAU2_DATA_DIR")
|
||||
if data_dir is None:
|
||||
raise ValueError("TAU2_DATA_DIR must be set")
|
||||
tasks_path = Path(data_dir) / "tau2/domains/airline/tasks.json"
|
||||
with tasks_path.open("r") as f:
|
||||
dataset = json.load(f)
|
||||
|
||||
# Serialize complex task objects to prevent HuggingFace tokenizer issues
|
||||
dataset = [{"id": task["id"], "data": json.dumps(task)} for task in dataset]
|
||||
|
||||
# Deterministic train/val split (25/25) for reproducible experiments
|
||||
random_state = random.Random(42) # noqa: S311
|
||||
indices = list(range(len(dataset)))
|
||||
random_state.shuffle(indices)
|
||||
train_indices = indices[: int(len(dataset) * 0.5)]
|
||||
val_indices = indices[int(len(dataset) * 0.5) :]
|
||||
print(f"Train indices: {train_indices}")
|
||||
print(f"Val indices: {val_indices}")
|
||||
train_dataset = [dataset[i] for i in train_indices]
|
||||
val_dataset = [dataset[i] for i in val_indices]
|
||||
|
||||
return cast(Dataset[SerializedTask], train_dataset), cast(Dataset[SerializedTask], val_dataset)
|
||||
|
||||
|
||||
# Alternative to @rollout: LitAgent class for advanced scenarios
|
||||
# Use this approach when you need:
|
||||
# - Agent filtering (training only specific agents in multi-agent setup)
|
||||
# - Resource management (multiple LLMs, databases, etc.)
|
||||
# - Complex initialization logic
|
||||
class Tau2Agent(LitAgent):
|
||||
"""Class-based agent with advanced resource management and agent filtering."""
|
||||
|
||||
async def rollout_async(self, task: SerializedTask, resources: NamedResources, rollout: Rollout) -> float:
|
||||
"""The main rollout method. Similar to @rollout but with more control."""
|
||||
llm = resources.get("main_llm")
|
||||
if not isinstance(llm, LLM):
|
||||
raise ValueError("main_llm must be an instance of LLM")
|
||||
|
||||
openai_base_url = os.getenv("OPENAI_BASE_URL")
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
if openai_base_url is None:
|
||||
raise ValueError("OPENAI_BASE_URL must be set")
|
||||
if openai_api_key is None:
|
||||
raise ValueError("OPENAI_API_KEY must be set")
|
||||
|
||||
# Deserialize the complex task object
|
||||
task_data = json.loads(task["data"])
|
||||
task_obj = Tau2Task(**task_data)
|
||||
|
||||
# Multi-agent setup: assistant (trainable) + user simulator (fixed)
|
||||
runner = Tau2TaskRunner(
|
||||
max_steps=100,
|
||||
assistant_window_size=4000,
|
||||
assistant_sampling_temperature=llm.sampling_parameters.get("temperature", 0.0),
|
||||
)
|
||||
|
||||
# Assistant agent: uses the model being trained
|
||||
assistant_chat_client = OpenAIChatClient(
|
||||
base_url=llm.endpoint, # vLLM endpoint for the model being trained
|
||||
api_key=openai_api_key,
|
||||
ai_model_id=llm.model, # Model ID being trained
|
||||
)
|
||||
|
||||
# User simulator: uses a fixed, capable model for consistent simulation
|
||||
user_simulator_chat_client = OpenAIChatClient(
|
||||
base_url=openai_base_url, # External API endpoint
|
||||
api_key=openai_api_key,
|
||||
ai_model_id="gpt-4.1", # Fixed model for user simulator
|
||||
)
|
||||
|
||||
try:
|
||||
# Run the multi-agent conversation
|
||||
conversation = await runner.run(task_obj, assistant_chat_client, user_simulator_chat_client)
|
||||
except Exception:
|
||||
# Handle failures gracefully - assign low reward to discourage problematic behavior
|
||||
# Common issues: tool calling errors, timeout, invalid responses
|
||||
traceback.print_exc()
|
||||
return 0.0
|
||||
|
||||
# Use Tau2's built-in evaluation metrics
|
||||
evaluation = runner.evaluate(task_obj, conversation, runner.termination_reason)
|
||||
|
||||
# Return the evaluation score
|
||||
return evaluation # noqa: RET504
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entrypoint."""
|
||||
# RL config with higher resource requirements and W&B logging
|
||||
rl_training_config = {
|
||||
"agentlightning": {
|
||||
"port": 9999,
|
||||
},
|
||||
"algorithm": {"adv_estimator": "grpo"},
|
||||
"data": {
|
||||
"train_batch_size": 8,
|
||||
"max_prompt_length": 8192,
|
||||
"max_response_length": 2048,
|
||||
},
|
||||
"actor_rollout_ref": {
|
||||
"rollout": {
|
||||
"tensor_model_parallel_size": 1,
|
||||
"n": 8, # Higher repetition for more data per task
|
||||
"log_prob_micro_batch_size_per_gpu": 4,
|
||||
"multi_turn": {"format": "hermes"},
|
||||
"name": "vllm",
|
||||
"gpu_memory_utilization": 0.8, # Higher utilization for 80GB GPU
|
||||
},
|
||||
"actor": {
|
||||
"ppo_mini_batch_size": 8,
|
||||
"ppo_micro_batch_size_per_gpu": 4,
|
||||
"optim": {"lr": 1e-6},
|
||||
"use_kl_loss": False,
|
||||
"clip_ratio_low": 0.2,
|
||||
"clip_ratio_high": 0.3,
|
||||
"fsdp_config": {
|
||||
"param_offload": True,
|
||||
"optimizer_offload": True,
|
||||
},
|
||||
},
|
||||
# Reference model config
|
||||
"ref": {
|
||||
"log_prob_micro_batch_size_per_gpu": 8,
|
||||
"fsdp_config": {"param_offload": True},
|
||||
},
|
||||
# Common configs for the model
|
||||
"model": {
|
||||
"path": "Qwen/Qwen2.5-1.5B-Instruct",
|
||||
"use_remove_padding": True,
|
||||
"enable_gradient_checkpointing": True,
|
||||
},
|
||||
},
|
||||
"trainer": {
|
||||
"n_gpus_per_node": 1,
|
||||
"val_before_train": True,
|
||||
"logger": ["console", "wandb"], # Wandb for experiment tracking
|
||||
"project_name": "agent-framework-lab-lightning",
|
||||
"experiment_name": "tau2_agent",
|
||||
"nnodes": 1,
|
||||
"test_freq": 4,
|
||||
"total_epochs": 8,
|
||||
},
|
||||
}
|
||||
|
||||
lightning_init()
|
||||
patch_env_set_state() # Tau2-specific environment setup
|
||||
|
||||
train_dataset, val_dataset = _load_dataset()
|
||||
|
||||
# Key difference with math_agent: trained_agents parameter specifies which agents to train
|
||||
# Only the assistant agent is trained; user simulator remains fixed
|
||||
tau2_agent = Tau2Agent(trained_agents=ASSISTANT_AGENT_ID)
|
||||
|
||||
trainer = Trainer(algorithm=VERL(rl_training_config), n_workers=4)
|
||||
trainer.fit(tau2_agent, train_dataset, val_data=val_dataset)
|
||||
|
||||
|
||||
def debug():
|
||||
"""Debug mode for testing multi-agent setup and Tau2 integration."""
|
||||
lightning_init()
|
||||
|
||||
train_dataset, _ = _load_dataset()
|
||||
tau2_agent = Tau2Agent(trained_agents=ASSISTANT_AGENT_ID)
|
||||
|
||||
openai_base_url = os.getenv("OPENAI_BASE_URL")
|
||||
if openai_base_url is None:
|
||||
raise ValueError("OPENAI_BASE_URL must be set")
|
||||
|
||||
patch_env_set_state() # Required for Tau2 environment
|
||||
|
||||
# Test with resources dict (different from @rollout LLM parameter)
|
||||
asyncio.run(
|
||||
tau2_agent.rollout_async(
|
||||
train_dataset[0],
|
||||
resources={"main_llm": LLM(model="gpt-4.1", endpoint=openai_base_url)},
|
||||
rollout=Rollout(rollout_id="dummy"),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--debug", action="store_true")
|
||||
args = parser.parse_args()
|
||||
if args.debug:
|
||||
debug()
|
||||
else:
|
||||
main()
|
||||
@@ -2,16 +2,162 @@
|
||||
|
||||
"""Tests for lightning module."""
|
||||
|
||||
from agent_framework_lab_lightning import __version__
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
from agent_framework import (
|
||||
AgentExecutor,
|
||||
ChatAgent,
|
||||
WorkflowBuilder,
|
||||
)
|
||||
from agent_framework.openai import OpenAIChatClient
|
||||
from agent_framework_lab_lightning import init
|
||||
from agentlightning.adapter import TraceTripletAdapter
|
||||
from agentlightning.tracer import AgentOpsTracer
|
||||
from openai.types.chat import ChatCompletion, ChatCompletionMessage
|
||||
from openai.types.chat.chat_completion import Choice
|
||||
|
||||
|
||||
class TestLightning:
|
||||
"""Test the lightning module."""
|
||||
def test_import():
|
||||
"""Test that the module can be imported."""
|
||||
|
||||
def test_version(self):
|
||||
"""Test package version is defined."""
|
||||
assert __version__ is not None
|
||||
# In development mode, version falls back to "0.0.0"
|
||||
# In installed mode, it would be the actual package version
|
||||
assert isinstance(__version__, str)
|
||||
assert len(__version__) > 0
|
||||
|
||||
@pytest.fixture
|
||||
def workflow_two_agents():
|
||||
"""Test a workflow with two OpenAI chat agents where first agent's result passes to second agent."""
|
||||
|
||||
# Mock OpenAI responses
|
||||
first_agent_response = ChatCompletion(
|
||||
id="chatcmpl-123",
|
||||
object="chat.completion",
|
||||
created=1677652288,
|
||||
model="gpt-4o",
|
||||
choices=[
|
||||
Choice(
|
||||
index=0,
|
||||
message=ChatCompletionMessage(role="assistant", content="Analyzed data shows trend upward"),
|
||||
finish_reason="stop",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
second_agent_response = ChatCompletion(
|
||||
id="chatcmpl-456",
|
||||
object="chat.completion",
|
||||
created=1677652289,
|
||||
model="gpt-4o",
|
||||
choices=[
|
||||
Choice(
|
||||
index=0,
|
||||
message=ChatCompletionMessage(
|
||||
role="assistant",
|
||||
content="Based on the analysis 'Analyzed data shows trend upward', I recommend investing",
|
||||
),
|
||||
finish_reason="stop",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
# Create mock OpenAI clients
|
||||
with patch.dict(
|
||||
"os.environ",
|
||||
{
|
||||
"OPENAI_API_KEY": "test-key",
|
||||
"OPENAI_CHAT_MODEL_ID": "gpt-4o",
|
||||
},
|
||||
):
|
||||
first_chat_client = OpenAIChatClient()
|
||||
second_chat_client = OpenAIChatClient()
|
||||
|
||||
# Mock the OpenAI API calls
|
||||
with (
|
||||
patch.object(
|
||||
first_chat_client.client.chat.completions,
|
||||
"create",
|
||||
new_callable=AsyncMock,
|
||||
return_value=first_agent_response,
|
||||
),
|
||||
patch.object(
|
||||
second_chat_client.client.chat.completions,
|
||||
"create",
|
||||
new_callable=AsyncMock,
|
||||
return_value=second_agent_response,
|
||||
),
|
||||
):
|
||||
# Create the two agents
|
||||
analyzer_agent = ChatAgent(
|
||||
chat_client=first_chat_client,
|
||||
name="DataAnalyzer",
|
||||
instructions="You are a data analyst. Analyze the given data and provide insights.",
|
||||
)
|
||||
|
||||
advisor_agent = ChatAgent(
|
||||
chat_client=second_chat_client,
|
||||
name="InvestmentAdvisor",
|
||||
instructions="You are an investment advisor. Based on analysis results, provide recommendations.",
|
||||
)
|
||||
|
||||
analyzer_executor = AgentExecutor(id="analyzer", agent=analyzer_agent)
|
||||
advisor_executor = AgentExecutor(id="advisor", agent=advisor_agent)
|
||||
|
||||
# Build workflow: analyzer -> advisor
|
||||
workflow = (
|
||||
WorkflowBuilder()
|
||||
.set_start_executor(analyzer_executor)
|
||||
.add_edge(analyzer_executor, advisor_executor)
|
||||
.build()
|
||||
)
|
||||
|
||||
yield workflow
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_openai_workflow_two_agents(workflow_two_agents):
|
||||
events = await workflow_two_agents.run("Please analyze the quarterly sales data")
|
||||
|
||||
assert "Based on the analysis 'Analyzed data shows trend upward', I recommend investing" in events.get_outputs()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_observability(workflow_two_agents):
|
||||
r"""Expected trace tree:
|
||||
|
||||
[workflow.run]
|
||||
/ \
|
||||
[analyzer] [advisor]
|
||||
/ \ / \
|
||||
[DataAnalyzer] [send] [Investment] [send]
|
||||
| |
|
||||
[chat gpt-4o] [chat gpt-4o]
|
||||
"""
|
||||
init()
|
||||
|
||||
tracer = AgentOpsTracer()
|
||||
try:
|
||||
tracer.init()
|
||||
tracer.init_worker(0)
|
||||
|
||||
with tracer.trace_context():
|
||||
await workflow_two_agents.run("Please analyze the quarterly sales data")
|
||||
|
||||
triplets = TraceTripletAdapter(agent_match=None, llm_call_match="chat").adapt(tracer.get_last_trace())
|
||||
assert len(triplets) == 2
|
||||
|
||||
triplets = TraceTripletAdapter(agent_match="analyzer", llm_call_match="chat").adapt(tracer.get_last_trace())
|
||||
assert len(triplets) == 1
|
||||
|
||||
triplets = TraceTripletAdapter(agent_match="advisor", llm_call_match="chat").adapt(tracer.get_last_trace())
|
||||
assert len(triplets) == 1
|
||||
|
||||
# Parent agent is not matched
|
||||
triplets = TraceTripletAdapter(agent_match="DataAnalyzer", llm_call_match="chat").adapt(tracer.get_last_trace())
|
||||
assert len(triplets) == 0
|
||||
|
||||
triplets = TraceTripletAdapter(agent_match="InvestmentAdvisor|advisor", llm_call_match="chat").adapt(
|
||||
tracer.get_last_trace()
|
||||
)
|
||||
assert len(triplets) == 1
|
||||
|
||||
finally:
|
||||
tracer.teardown_worker(0)
|
||||
tracer.teardown()
|
||||
|
||||
@@ -36,7 +36,8 @@ gaia = [
|
||||
|
||||
# Lightning RL training module dependencies
|
||||
lightning = [
|
||||
"pydantic>=2.0.0",
|
||||
# Till 0.2.0 is released
|
||||
"agentlightning @ git+https://github.com/microsoft/agent-lightning@138ad0e48780b65ccefa628ee7a5fb9fb27aca01",
|
||||
]
|
||||
|
||||
# TAU2 benchmark module dependencies
|
||||
@@ -48,6 +49,10 @@ tau2 = [
|
||||
"tau2@ git+https://github.com/sierra-research/tau2-bench@5ba9e3e56db57c5e4114bf7f901291f09b2c5619",
|
||||
]
|
||||
|
||||
# Dependencies for math-related training
|
||||
math = [
|
||||
"sympy>=1.13.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
gaia_viewer = "agent_framework_lab_gaia:viewer_main"
|
||||
@@ -82,6 +87,7 @@ agent_framework_lab_tau2 = ["py.typed"]
|
||||
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
extend-exclude = ["**/data/**"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
ignore = ["T201", "ASYNC230", "INP001"] # Allow print statements, blocking file operations, and implicit namespace packages in lab modules
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import importlib.metadata
|
||||
|
||||
from ._tau2_utils import patch_env_set_state, unpatch_env_set_state
|
||||
from .runner import TaskRunner
|
||||
from .runner import ASSISTANT_AGENT_ID, ORCHESTRATOR_ID, USER_SIMULATOR_ID, TaskRunner
|
||||
|
||||
try:
|
||||
__version__ = importlib.metadata.version(__name__)
|
||||
@@ -13,6 +13,9 @@ except importlib.metadata.PackageNotFoundError:
|
||||
__version__ = "0.0.0" # Fallback for development mode
|
||||
|
||||
__all__ = [
|
||||
"ASSISTANT_AGENT_ID",
|
||||
"ORCHESTRATOR_ID",
|
||||
"USER_SIMULATOR_ID",
|
||||
"TaskRunner",
|
||||
"patch_env_set_state",
|
||||
"unpatch_env_set_state",
|
||||
|
||||
@@ -32,6 +32,8 @@ from ._message_utils import flip_messages, log_messages
|
||||
from ._sliding_window import SlidingWindowChatMessageStore
|
||||
from ._tau2_utils import convert_agent_framework_messages_to_tau2_messages, convert_tau2_tool_to_ai_function
|
||||
|
||||
__all__ = ["ASSISTANT_AGENT_ID", "ORCHESTRATOR_ID", "USER_SIMULATOR_ID", "TaskRunner"]
|
||||
|
||||
# Agent instructions matching tau2's LLMAgent
|
||||
ASSISTANT_AGENT_INSTRUCTION = """
|
||||
You are a customer service agent that helps the user according to the <policy> provided below.
|
||||
@@ -413,5 +415,8 @@ class TaskRunner:
|
||||
domain="airline",
|
||||
)
|
||||
|
||||
logger.info(f"Evaluation completed - Reward: {self.full_reward_info.reward}, Info: {self.full_reward_info}")
|
||||
return self.full_reward_info.reward # type: ignore[no-any-return]
|
||||
logger.info(
|
||||
f"Evaluation completed - Reward: {self.full_reward_info.reward if self.full_reward_info else None}, "
|
||||
f"Info: {self.full_reward_info}"
|
||||
)
|
||||
return self.full_reward_info.reward if self.full_reward_info else 0.0
|
||||
|
||||
Generated
+245
-18
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
revision = 2
|
||||
requires-python = ">=3.10"
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.13' and sys_platform == 'darwin'",
|
||||
@@ -258,7 +258,10 @@ gaia = [
|
||||
{ name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
lightning = [
|
||||
{ name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "agentlightning", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
math = [
|
||||
{ name = "sympy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
tau2 = [
|
||||
{ name = "loguru", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
@@ -272,19 +275,20 @@ tau2 = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "agent-framework", editable = "packages/main" },
|
||||
{ name = "agentlightning", marker = "extra == 'lightning'", git = "https://github.com/microsoft/agent-lightning?rev=138ad0e48780b65ccefa628ee7a5fb9fb27aca01" },
|
||||
{ name = "huggingface-hub", marker = "extra == 'gaia'", specifier = ">=0.20.0" },
|
||||
{ name = "loguru", marker = "extra == 'tau2'", specifier = ">=0.7.3" },
|
||||
{ name = "numpy", marker = "extra == 'tau2'" },
|
||||
{ name = "opentelemetry-api", marker = "extra == 'gaia'", specifier = ">=1.24.0" },
|
||||
{ name = "orjson", marker = "extra == 'gaia'", specifier = ">=3.8.0" },
|
||||
{ name = "pydantic", marker = "extra == 'gaia'", specifier = ">=2.0.0" },
|
||||
{ name = "pydantic", marker = "extra == 'lightning'", specifier = ">=2.0.0" },
|
||||
{ name = "pydantic", marker = "extra == 'tau2'", specifier = ">=2.0.0" },
|
||||
{ name = "sympy", marker = "extra == 'math'", specifier = ">=1.13.0" },
|
||||
{ name = "tau2", marker = "extra == 'tau2'", git = "https://github.com/sierra-research/tau2-bench?rev=5ba9e3e56db57c5e4114bf7f901291f09b2c5619" },
|
||||
{ name = "tiktoken", marker = "extra == 'tau2'", specifier = ">=0.11.0" },
|
||||
{ name = "tqdm", marker = "extra == 'gaia'", specifier = ">=4.60.0" },
|
||||
]
|
||||
provides-extras = ["gaia", "lightning", "tau2"]
|
||||
provides-extras = ["gaia", "lightning", "tau2", "math"]
|
||||
|
||||
[[package]]
|
||||
name = "agent-framework-mem0"
|
||||
@@ -407,6 +411,51 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "agent-framework", editable = "packages/main" }]
|
||||
|
||||
[[package]]
|
||||
name = "agentlightning"
|
||||
version = "0.2.0"
|
||||
source = { git = "https://github.com/microsoft/agent-lightning?rev=138ad0e48780b65ccefa628ee7a5fb9fb27aca01#138ad0e48780b65ccefa628ee7a5fb9fb27aca01" }
|
||||
dependencies = [
|
||||
{ name = "agentops", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "aiohttp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "fastapi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "flask", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "graphviz", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "httpdbg", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-sdk", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "psutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "setproctitle", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "uvicorn", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "agentops"
|
||||
version = "0.4.21"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "httpx", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-exporter-otlp-proto-http", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-instrumentation", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-sdk", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "opentelemetry-semantic-conventions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "ordered-set", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "psutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "termcolor", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "wrapt", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0a/c4/023fe976169c57b1edd71f4c08d6dedaf66814f5b25ecf59b3a8540311ab/agentops-0.4.21.tar.gz", hash = "sha256:47759c6dfd6ea58bad2f7764257e4778cb2e34ae180cef642f60f56adced6510", size = 430861, upload-time = "2025-08-29T06:36:55.323Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/63/3e48da56d5121ddcefef8645ad5a3446b0974154111a14bf75ea2b5b3cc3/agentops-0.4.21-py3-none-any.whl", hash = "sha256:93b098ea77bc5f64dcae5031a8292531cb446d9d66e6c7ef2f21a66d4e4fb2f0", size = 309579, upload-time = "2025-08-29T06:36:53.855Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aiofiles"
|
||||
version = "24.1.0"
|
||||
@@ -752,6 +801,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5", size = 12313, upload-time = "2025-07-02T02:27:14.263Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
version = "1.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cachetools"
|
||||
version = "5.5.2"
|
||||
@@ -1371,7 +1429,7 @@ name = "exceptiongroup"
|
||||
version = "1.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions", marker = "(python_full_version < '3.13' and sys_platform == 'darwin') or (python_full_version < '3.13' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform == 'win32')" },
|
||||
{ name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
|
||||
wheels = [
|
||||
@@ -1471,6 +1529,23 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/6d/8f5307d26ce700a89e5a67d1e1ad15eff977211f9ed3ae90d7b0d67f4e66/fixedint-0.1.6-py3-none-any.whl", hash = "sha256:b8cf9f913735d2904deadda7a6daa9f57100599da1de57a7448ea1be75ae8c9c", size = 12702, upload-time = "2020-06-20T22:14:15.454Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flask"
|
||||
version = "3.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "blinker", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "click", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "itsdangerous", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "jinja2", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
{ name = "werkzeug", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/6d/cfe3c0fcc5e477df242b98bfe186a4c34357b4847e87ecaef04507332dab/flask-3.1.2.tar.gz", hash = "sha256:bf656c15c80190ed628ad08cdfd3aaa35beb087855e2f494910aa3774cc4fd87", size = 720160, upload-time = "2025-08-19T21:03:21.205Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/f9/7f9263c5695f4bd0023734af91bedb2ff8209e8de6ead162f35d8dc762fd/flask-3.1.2-py3-none-any.whl", hash = "sha256:ca1d8112ec8a6158cc29ea4858963350011b5c846a414cdb7a954aa9e967d03c", size = 103308, upload-time = "2025-08-19T21:03:19.499Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fonttools"
|
||||
version = "4.60.0"
|
||||
@@ -1867,6 +1942,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpdbg"
|
||||
version = "2.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/11/20/3a48a46a5c2e36dfd2971923aabe58d41e4f7e1367b8bd69243f4d048c4e/httpdbg-2.0.2.tar.gz", hash = "sha256:ac69eff94f9469df1696d5094b5cdeaeaecece5850adacd4314cf8ee4d7a87af", size = 79482, upload-time = "2025-09-14T18:01:12.272Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/23/ae/8ad6048d455344376947d6630e82142e0e7b0e5bbe267028571b9aa8f06e/httpdbg-2.0.2-py3-none-any.whl", hash = "sha256:a53c343e78292476a69da90e7fa48675960cbf3704127456b6922cd2bd33eaad", size = 87057, upload-time = "2025-09-14T18:01:10.774Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httptools"
|
||||
version = "0.6.4"
|
||||
@@ -2017,6 +2101,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320, upload-time = "2024-10-08T23:04:09.501Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
@@ -2622,6 +2715,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/3c/541c4b30815ab90ebfbb51df15d0b4254f2f9f1e2b4907ab229300d5e6f2/ml_dtypes-0.5.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ab039ffb40f3dc0aeeeba84fd6c3452781b5e15bef72e2d10bcb33e4bbffc39", size = 5285284, upload-time = "2025-07-29T18:39:11.532Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mpmath"
|
||||
version = "1.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "msal"
|
||||
version = "1.34.0"
|
||||
@@ -3325,6 +3427,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/a3/0a1430c42c6d34d8372a16c104e7408028f0c30270d8f3eb6cccf2e82934/opentelemetry_util_http-0.58b0-py3-none-any.whl", hash = "sha256:6c6b86762ed43025fbd593dc5f700ba0aa3e09711aedc36fd48a13b23d8cb1e7", size = 7652, upload-time = "2025-09-11T11:42:09.682Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-set"
|
||||
version = "4.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4c/ca/bfac8bc689799bcca4157e0e0ced07e70ce125193fc2e166d2e685b7e2fe/ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8", size = 12826, upload-time = "2022-01-26T14:38:56.6Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/33/55/af02708f230eb77084a299d7b08175cff006dea4f2721074b92cdb0296c0/ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562", size = 7634, upload-time = "2022-01-26T14:38:48.677Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "orderly-set"
|
||||
version = "5.5.0"
|
||||
@@ -3413,11 +3524,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "25.0"
|
||||
version = "24.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3814,18 +3925,17 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "psutil"
|
||||
version = "7.1.0"
|
||||
version = "7.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/31/4723d756b59344b643542936e37a31d1d3204bcdc42a7daa8ee9eb06fb50/psutil-7.1.0.tar.gz", hash = "sha256:655708b3c069387c8b77b072fc429a57d0e214221d01c0a772df7dfedcb3bcd2", size = 497660, upload-time = "2025-09-17T20:14:52.902Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2a/80/336820c1ad9286a4ded7e845b2eccfcb27851ab8ac6abece774a6ff4d3de/psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456", size = 497003, upload-time = "2025-02-13T21:54:07.946Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/62/ce4051019ee20ce0ed74432dd73a5bb087a6704284a470bb8adff69a0932/psutil-7.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76168cef4397494250e9f4e73eb3752b146de1dd950040b29186d0cce1d5ca13", size = 245242, upload-time = "2025-09-17T20:14:56.126Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/61/f76959fba841bf5b61123fbf4b650886dc4094c6858008b5bf73d9057216/psutil-7.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:5d007560c8c372efdff9e4579c2846d71de737e4605f611437255e81efcca2c5", size = 246682, upload-time = "2025-09-17T20:14:58.25Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/7a/37c99d2e77ec30d63398ffa6a660450b8a62517cabe44b3e9bae97696e8d/psutil-7.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22e4454970b32472ce7deaa45d045b34d3648ce478e26a04c7e858a0a6e75ff3", size = 287994, upload-time = "2025-09-17T20:14:59.901Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/de/04c8c61232f7244aa0a4b9a9fbd63a89d5aeaf94b2fc9d1d16e2faa5cbb0/psutil-7.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c70e113920d51e89f212dd7be06219a9b88014e63a4cec69b684c327bc474e3", size = 291163, upload-time = "2025-09-17T20:15:01.481Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/58/c4f976234bf6d4737bc8c02a81192f045c307b72cf39c9e5c5a2d78927f6/psutil-7.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d4a113425c037300de3ac8b331637293da9be9713855c4fc9d2d97436d7259d", size = 293625, upload-time = "2025-09-17T20:15:04.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/87/157c8e7959ec39ced1b11cc93c730c4fb7f9d408569a6c59dbd92ceb35db/psutil-7.1.0-cp37-abi3-win32.whl", hash = "sha256:09ad740870c8d219ed8daae0ad3b726d3bf9a028a198e7f3080f6a1888b99bca", size = 244812, upload-time = "2025-09-17T20:15:07.462Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/e9/b44c4f697276a7a95b8e94d0e320a7bf7f3318521b23de69035540b39838/psutil-7.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:57f5e987c36d3146c0dd2528cd42151cf96cd359b9d67cfff836995cc5df9a3d", size = 247965, upload-time = "2025-09-17T20:15:09.673Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/65/1070a6e3c036f39142c2820c4b52e9243246fcfc3f96239ac84472ba361e/psutil-7.1.0-cp37-abi3-win_arm64.whl", hash = "sha256:6937cb68133e7c97b6cc9649a570c9a18ba0efebed46d8c5dae4c07fa1b67a07", size = 244971, upload-time = "2025-09-17T20:15:12.262Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/e6/2d26234410f8b8abdbf891c9da62bee396583f713fb9f3325a4760875d22/psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25", size = 238051, upload-time = "2025-02-13T21:54:12.36Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8b/30f930733afe425e3cbfc0e1468a30a18942350c1a8816acfade80c005c4/psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da", size = 239535, upload-time = "2025-02-13T21:54:16.07Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/ed/d362e84620dd22876b55389248e522338ed1bf134a5edd3b8231d7207f6d/psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91", size = 275004, upload-time = "2025-02-13T21:54:18.662Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/b9/b0eb3f3cbcb734d930fdf839431606844a825b23eaf9a6ab371edac8162c/psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34", size = 277986, upload-time = "2025-02-13T21:54:21.811Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/a2/709e0fe2f093556c17fbafda93ac032257242cabcc7ff3369e2cb76a97aa/psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993", size = 279544, upload-time = "2025-02-13T21:54:24.68Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/e6/eecf58810b9d12e6427369784efe814a1eec0f492084ce8eb8f4d89d6d61/psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99", size = 241053, upload-time = "2025-02-13T21:54:34.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/1b/6921afe68c74868b4c9fa424dad3be35b095e16687989ebbb50ce4fceb7c/psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553", size = 244885, upload-time = "2025-02-13T21:54:37.486Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4857,6 +4967,90 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setproctitle"
|
||||
version = "1.3.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8d/48/49393a96a2eef1ab418b17475fb92b8fcfad83d099e678751b05472e69de/setproctitle-1.3.7.tar.gz", hash = "sha256:bc2bc917691c1537d5b9bca1468437176809c7e11e5694ca79a9ca12345dcb9e", size = 27002, upload-time = "2025-09-05T12:51:25.278Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/48/fb401ec8c4953d519d05c87feca816ad668b8258448ff60579ac7a1c1386/setproctitle-1.3.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cf555b6299f10a6eb44e4f96d2f5a3884c70ce25dc5c8796aaa2f7b40e72cb1b", size = 18079, upload-time = "2025-09-05T12:49:07.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/a3/c2b0333c2716fb3b4c9a973dd113366ac51b4f8d56b500f4f8f704b4817a/setproctitle-1.3.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:690b4776f9c15aaf1023bb07d7c5b797681a17af98a4a69e76a1d504e41108b7", size = 13099, upload-time = "2025-09-05T12:49:09.222Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/f8/17bda581c517678260e6541b600eeb67745f53596dc077174141ba2f6702/setproctitle-1.3.7-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:00afa6fc507967d8c9d592a887cdc6c1f5742ceac6a4354d111ca0214847732c", size = 31793, upload-time = "2025-09-05T12:49:10.297Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/d1/76a33ae80d4e788ecab9eb9b53db03e81cfc95367ec7e3fbf4989962fedd/setproctitle-1.3.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e02667f6b9fc1238ba753c0f4b0a37ae184ce8f3bbbc38e115d99646b3f4cd3", size = 32779, upload-time = "2025-09-05T12:49:12.157Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/27/1a07c38121967061564f5e0884414a5ab11a783260450172d4fc68c15621/setproctitle-1.3.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:83fcd271567d133eb9532d3b067c8a75be175b2b3b271e2812921a05303a693f", size = 34578, upload-time = "2025-09-05T12:49:13.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/d4/725e6353935962d8bb12cbf7e7abba1d0d738c7f6935f90239d8e1ccf913/setproctitle-1.3.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13fe37951dda1a45c35d77d06e3da5d90e4f875c4918a7312b3b4556cfa7ff64", size = 32030, upload-time = "2025-09-05T12:49:15.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/24/e4677ae8e1cb0d549ab558b12db10c175a889be0974c589c428fece5433e/setproctitle-1.3.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a05509cfb2059e5d2ddff701d38e474169e9ce2a298cf1b6fd5f3a213a553fe5", size = 33363, upload-time = "2025-09-05T12:49:16.829Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/d4/69ce66e4373a48fdbb37489f3ded476bb393e27f514968c3a69a67343ae0/setproctitle-1.3.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6da835e76ae18574859224a75db6e15c4c2aaa66d300a57efeaa4c97ca4c7381", size = 31508, upload-time = "2025-09-05T12:49:18.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/5a/42c1ed0e9665d068146a68326529b5686a1881c8b9197c2664db4baf6aeb/setproctitle-1.3.7-cp310-cp310-win32.whl", hash = "sha256:9e803d1b1e20240a93bac0bc1025363f7f80cb7eab67dfe21efc0686cc59ad7c", size = 12558, upload-time = "2025-09-05T12:49:19.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/fe/dd206cc19a25561921456f6cb12b405635319299b6f366e0bebe872abc18/setproctitle-1.3.7-cp310-cp310-win_amd64.whl", hash = "sha256:a97200acc6b64ec4cada52c2ecaf1fba1ef9429ce9c542f8a7db5bcaa9dcbd95", size = 13245, upload-time = "2025-09-05T12:49:21.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/cd/1b7ba5cad635510720ce19d7122154df96a2387d2a74217be552887c93e5/setproctitle-1.3.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a600eeb4145fb0ee6c287cb82a2884bd4ec5bbb076921e287039dcc7b7cc6dd0", size = 18085, upload-time = "2025-09-05T12:49:22.183Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/1a/b2da0a620490aae355f9d72072ac13e901a9fec809a6a24fc6493a8f3c35/setproctitle-1.3.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:97a090fed480471bb175689859532709e28c085087e344bca45cf318034f70c4", size = 13097, upload-time = "2025-09-05T12:49:23.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/2e/bd03ff02432a181c1787f6fc2a678f53b7dacdd5ded69c318fe1619556e8/setproctitle-1.3.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1607b963e7b53e24ec8a2cb4e0ab3ae591d7c6bf0a160feef0551da63452b37f", size = 32191, upload-time = "2025-09-05T12:49:24.567Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/78/1e62fc0937a8549f2220445ed2175daacee9b6764c7963b16148119b016d/setproctitle-1.3.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a20fb1a3974e2dab857870cf874b325b8705605cb7e7e8bcbb915bca896f52a9", size = 33203, upload-time = "2025-09-05T12:49:25.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/3c/65edc65db3fa3df400cf13b05e9d41a3c77517b4839ce873aa6b4043184f/setproctitle-1.3.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f8d961bba676e07d77665204f36cffaa260f526e7b32d07ab3df6a2c1dfb44ba", size = 34963, upload-time = "2025-09-05T12:49:27.044Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/32/89157e3de997973e306e44152522385f428e16f92f3cf113461489e1e2ee/setproctitle-1.3.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:db0fd964fbd3a9f8999b502f65bd2e20883fdb5b1fae3a424e66db9a793ed307", size = 32398, upload-time = "2025-09-05T12:49:28.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/18/77a765a339ddf046844cb4513353d8e9dcd8183da9cdba6e078713e6b0b2/setproctitle-1.3.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:db116850fcf7cca19492030f8d3b4b6e231278e8fe097a043957d22ce1bdf3ee", size = 33657, upload-time = "2025-09-05T12:49:30.323Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/63/f0b6205c64d74d2a24a58644a38ec77bdbaa6afc13747e75973bf8904932/setproctitle-1.3.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:316664d8b24a5c91ee244460bdaf7a74a707adaa9e14fbe0dc0a53168bb9aba1", size = 31836, upload-time = "2025-09-05T12:49:32.309Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/51/e1277f9ba302f1a250bbd3eedbbee747a244b3cc682eb58fb9733968f6d8/setproctitle-1.3.7-cp311-cp311-win32.whl", hash = "sha256:b74774ca471c86c09b9d5037c8451fff06bb82cd320d26ae5a01c758088c0d5d", size = 12556, upload-time = "2025-09-05T12:49:33.529Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/7b/822a23f17e9003dfdee92cd72758441ca2a3680388da813a371b716fb07f/setproctitle-1.3.7-cp311-cp311-win_amd64.whl", hash = "sha256:acb9097213a8dd3410ed9f0dc147840e45ca9797785272928d4be3f0e69e3be4", size = 13243, upload-time = "2025-09-05T12:49:34.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/f0/2dc88e842077719d7384d86cc47403e5102810492b33680e7dadcee64cd8/setproctitle-1.3.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2dc99aec591ab6126e636b11035a70991bc1ab7a261da428491a40b84376654e", size = 18049, upload-time = "2025-09-05T12:49:36.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/b4/50940504466689cda65680c9e9a1e518e5750c10490639fa687489ac7013/setproctitle-1.3.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdd8aa571b7aa39840fdbea620e308a19691ff595c3a10231e9ee830339dd798", size = 13079, upload-time = "2025-09-05T12:49:38.088Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/99/71630546b9395b095f4082be41165d1078204d1696c2d9baade3de3202d0/setproctitle-1.3.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2906b6c7959cdb75f46159bf0acd8cc9906cf1361c9e1ded0d065fe8f9039629", size = 32932, upload-time = "2025-09-05T12:49:39.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/22/cee06af4ffcfb0e8aba047bd44f5262e644199ae7527ae2c1f672b86495c/setproctitle-1.3.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6915964a6dda07920a1159321dcd6d94fc7fc526f815ca08a8063aeca3c204f1", size = 33736, upload-time = "2025-09-05T12:49:40.565Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/00/a5949a8bb06ef5e7df214fc393bb2fb6aedf0479b17214e57750dfdd0f24/setproctitle-1.3.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cff72899861c765bd4021d1ff1c68d60edc129711a2fdba77f9cb69ef726a8b6", size = 35605, upload-time = "2025-09-05T12:49:42.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/3a/50caca532a9343828e3bf5778c7a84d6c737a249b1796d50dd680290594d/setproctitle-1.3.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b7cb05bd446687ff816a3aaaf831047fc4c364feff7ada94a66024f1367b448c", size = 33143, upload-time = "2025-09-05T12:49:43.515Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/14/b843a251296ce55e2e17c017d6b9f11ce0d3d070e9265de4ecad948b913d/setproctitle-1.3.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3a57b9a00de8cae7e2a1f7b9f0c2ac7b69372159e16a7708aa2f38f9e5cc987a", size = 34434, upload-time = "2025-09-05T12:49:45.31Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/b7/06145c238c0a6d2c4bc881f8be230bb9f36d2bf51aff7bddcb796d5eed67/setproctitle-1.3.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d8828b356114f6b308b04afe398ed93803d7fca4a955dd3abe84430e28d33739", size = 32795, upload-time = "2025-09-05T12:49:46.419Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/dc/ef76a81fac9bf27b84ed23df19c1f67391a753eed6e3c2254ebcb5133f56/setproctitle-1.3.7-cp312-cp312-win32.whl", hash = "sha256:b0304f905efc845829ac2bc791ddebb976db2885f6171f4a3de678d7ee3f7c9f", size = 12552, upload-time = "2025-09-05T12:49:47.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/5b/a9fe517912cd6e28cf43a212b80cb679ff179a91b623138a99796d7d18a0/setproctitle-1.3.7-cp312-cp312-win_amd64.whl", hash = "sha256:9888ceb4faea3116cf02a920ff00bfbc8cc899743e4b4ac914b03625bdc3c300", size = 13247, upload-time = "2025-09-05T12:49:49.16Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/2f/fcedcade3b307a391b6e17c774c6261a7166aed641aee00ed2aad96c63ce/setproctitle-1.3.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c3736b2a423146b5e62230502e47e08e68282ff3b69bcfe08a322bee73407922", size = 18047, upload-time = "2025-09-05T12:49:50.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/ae/afc141ca9631350d0a80b8f287aac79a76f26b6af28fd8bf92dae70dc2c5/setproctitle-1.3.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3384e682b158d569e85a51cfbde2afd1ab57ecf93ea6651fe198d0ba451196ee", size = 13073, upload-time = "2025-09-05T12:49:51.46Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/ed/0a4f00315bc02510395b95eec3d4aa77c07192ee79f0baae77ea7b9603d8/setproctitle-1.3.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0564a936ea687cd24dffcea35903e2a20962aa6ac20e61dd3a207652401492dd", size = 33284, upload-time = "2025-09-05T12:49:52.741Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/e4/adf3c4c0a2173cb7920dc9df710bcc67e9bcdbf377e243b7a962dc31a51a/setproctitle-1.3.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5d1cb3f81531f0eb40e13246b679a1bdb58762b170303463cb06ecc296f26d0", size = 34104, upload-time = "2025-09-05T12:49:54.416Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/4f/6daf66394152756664257180439d37047aa9a1cfaa5e4f5ed35e93d1dc06/setproctitle-1.3.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a7d159e7345f343b44330cbba9194169b8590cb13dae940da47aa36a72aa9929", size = 35982, upload-time = "2025-09-05T12:49:56.295Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/62/f2c0595403cf915db031f346b0e3b2c0096050e90e0be658a64f44f4278a/setproctitle-1.3.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0b5074649797fd07c72ca1f6bff0406f4a42e1194faac03ecaab765ce605866f", size = 33150, upload-time = "2025-09-05T12:49:58.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/29/10dd41cde849fb2f9b626c846b7ea30c99c81a18a5037a45cc4ba33c19a7/setproctitle-1.3.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:61e96febced3f61b766115381d97a21a6265a0f29188a791f6df7ed777aef698", size = 34463, upload-time = "2025-09-05T12:49:59.424Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/3c/cedd8eccfaf15fb73a2c20525b68c9477518917c9437737fa0fda91e378f/setproctitle-1.3.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:047138279f9463f06b858e579cc79580fbf7a04554d24e6bddf8fe5dddbe3d4c", size = 32848, upload-time = "2025-09-05T12:50:01.107Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/3e/0a0e27d1c9926fecccfd1f91796c244416c70bf6bca448d988638faea81d/setproctitle-1.3.7-cp313-cp313-win32.whl", hash = "sha256:7f47accafac7fe6535ba8ba9efd59df9d84a6214565108d0ebb1199119c9cbbd", size = 12544, upload-time = "2025-09-05T12:50:15.81Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/1b/6bf4cb7acbbd5c846ede1c3f4d6b4ee52744d402e43546826da065ff2ab7/setproctitle-1.3.7-cp313-cp313-win_amd64.whl", hash = "sha256:fe5ca35aeec6dc50cabab9bf2d12fbc9067eede7ff4fe92b8f5b99d92e21263f", size = 13235, upload-time = "2025-09-05T12:50:16.89Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/a4/d588d3497d4714750e3eaf269e9e8985449203d82b16b933c39bd3fc52a1/setproctitle-1.3.7-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:10e92915c4b3086b1586933a36faf4f92f903c5554f3c34102d18c7d3f5378e9", size = 18058, upload-time = "2025-09-05T12:50:02.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/77/7637f7682322a7244e07c373881c7e982567e2cb1dd2f31bd31481e45500/setproctitle-1.3.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:de879e9c2eab637f34b1a14c4da1e030c12658cdc69ee1b3e5be81b380163ce5", size = 13072, upload-time = "2025-09-05T12:50:03.601Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/09/f366eca0973cfbac1470068d1313fa3fe3de4a594683385204ec7f1c4101/setproctitle-1.3.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c18246d88e227a5b16248687514f95642505000442165f4b7db354d39d0e4c29", size = 34490, upload-time = "2025-09-05T12:50:04.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/36/611fc2ed149fdea17c3677e1d0df30d8186eef9562acc248682b91312706/setproctitle-1.3.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7081f193dab22df2c36f9fc6d113f3793f83c27891af8fe30c64d89d9a37e152", size = 35267, upload-time = "2025-09-05T12:50:06.015Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/a4/64e77d0671446bd5a5554387b69e1efd915274686844bea733714c828813/setproctitle-1.3.7-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cc9b901ce129350637426a89cfd650066a4adc6899e47822e2478a74023ff7c", size = 37376, upload-time = "2025-09-05T12:50:07.484Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/bc/ad9c664fe524fb4a4b2d3663661a5c63453ce851736171e454fa2cdec35c/setproctitle-1.3.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:80e177eff2d1ec172188d0d7fd9694f8e43d3aab76a6f5f929bee7bf7894e98b", size = 33963, upload-time = "2025-09-05T12:50:09.056Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/01/a36de7caf2d90c4c28678da1466b47495cbbad43badb4e982d8db8167ed4/setproctitle-1.3.7-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:23e520776c445478a67ee71b2a3c1ffdafbe1f9f677239e03d7e2cc635954e18", size = 35550, upload-time = "2025-09-05T12:50:10.791Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/68/17e8aea0ed5ebc17fbf03ed2562bfab277c280e3625850c38d92a7b5fcd9/setproctitle-1.3.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5fa1953126a3b9bd47049d58c51b9dac72e78ed120459bd3aceb1bacee72357c", size = 33727, upload-time = "2025-09-05T12:50:12.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/33/90a3bf43fe3a2242b4618aa799c672270250b5780667898f30663fd94993/setproctitle-1.3.7-cp313-cp313t-win32.whl", hash = "sha256:4a5e212bf438a4dbeece763f4962ad472c6008ff6702e230b4f16a037e2f6f29", size = 12549, upload-time = "2025-09-05T12:50:13.074Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/0e/50d1f07f3032e1f23d814ad6462bc0a138f369967c72494286b8a5228e40/setproctitle-1.3.7-cp313-cp313t-win_amd64.whl", hash = "sha256:cf2727b733e90b4f874bac53e3092aa0413fe1ea6d4f153f01207e6ce65034d9", size = 13243, upload-time = "2025-09-05T12:50:14.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/c7/43ac3a98414f91d1b86a276bc2f799ad0b4b010e08497a95750d5bc42803/setproctitle-1.3.7-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:80c36c6a87ff72eabf621d0c79b66f3bdd0ecc79e873c1e9f0651ee8bf215c63", size = 18052, upload-time = "2025-09-05T12:50:17.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/2c/dc258600a25e1a1f04948073826bebc55e18dbd99dc65a576277a82146fa/setproctitle-1.3.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b53602371a52b91c80aaf578b5ada29d311d12b8a69c0c17fbc35b76a1fd4f2e", size = 13071, upload-time = "2025-09-05T12:50:19.061Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/26/8e3bb082992f19823d831f3d62a89409deb6092e72fc6940962983ffc94f/setproctitle-1.3.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fcb966a6c57cf07cc9448321a08f3be6b11b7635be502669bc1d8745115d7e7f", size = 33180, upload-time = "2025-09-05T12:50:20.395Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/af/ae692a20276d1159dd0cf77b0bcf92cbb954b965655eb4a69672099bb214/setproctitle-1.3.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46178672599b940368d769474fe13ecef1b587d58bb438ea72b9987f74c56ea5", size = 34043, upload-time = "2025-09-05T12:50:22.454Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/b2/6a092076324dd4dac1a6d38482bedebbff5cf34ef29f58585ec76e47bc9d/setproctitle-1.3.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7f9e9e3ff135cbcc3edd2f4cf29b139f4aca040d931573102742db70ff428c17", size = 35892, upload-time = "2025-09-05T12:50:23.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/1a/8836b9f28cee32859ac36c3df85aa03e1ff4598d23ea17ca2e96b5845a8f/setproctitle-1.3.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:14c7eba8d90c93b0e79c01f0bd92a37b61983c27d6d7d5a3b5defd599113d60e", size = 32898, upload-time = "2025-09-05T12:50:25.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/22/8fabdc24baf42defb599714799d8445fe3ae987ec425a26ec8e80ea38f8e/setproctitle-1.3.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:9e64e98077fb30b6cf98073d6c439cd91deb8ebbf8fc62d9dbf52bd38b0c6ac0", size = 34308, upload-time = "2025-09-05T12:50:26.827Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/1b/b9bee9de6c8cdcb3b3a6cb0b3e773afdb86bbbc1665a3bfa424a4294fda2/setproctitle-1.3.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b91387cc0f02a00ac95dcd93f066242d3cca10ff9e6153de7ee07069c6f0f7c8", size = 32536, upload-time = "2025-09-05T12:50:28.5Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/0c/75e5f2685a5e3eda0b39a8b158d6d8895d6daf3ba86dec9e3ba021510272/setproctitle-1.3.7-cp314-cp314-win32.whl", hash = "sha256:52b054a61c99d1b72fba58b7f5486e04b20fefc6961cd76722b424c187f362ed", size = 12731, upload-time = "2025-09-05T12:50:43.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/ae/acddbce90d1361e1786e1fb421bc25baeb0c22ef244ee5d0176511769ec8/setproctitle-1.3.7-cp314-cp314-win_amd64.whl", hash = "sha256:5818e4080ac04da1851b3ec71e8a0f64e3748bf9849045180566d8b736702416", size = 13464, upload-time = "2025-09-05T12:50:45.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/6d/20886c8ff2e6d85e3cabadab6aab9bb90acaf1a5cfcb04d633f8d61b2626/setproctitle-1.3.7-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6fc87caf9e323ac426910306c3e5d3205cd9f8dcac06d233fcafe9337f0928a3", size = 18062, upload-time = "2025-09-05T12:50:29.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/60/26dfc5f198715f1343b95c2f7a1c16ae9ffa45bd89ffd45a60ed258d24ea/setproctitle-1.3.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6134c63853d87a4897ba7d5cc0e16abfa687f6c66fc09f262bb70d67718f2309", size = 13075, upload-time = "2025-09-05T12:50:31.604Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/9c/980b01f50d51345dd513047e3ba9e96468134b9181319093e61db1c47188/setproctitle-1.3.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1403d2abfd32790b6369916e2313dffbe87d6b11dca5bbd898981bcde48e7a2b", size = 34744, upload-time = "2025-09-05T12:50:32.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/b4/82cd0c86e6d1c4538e1a7eb908c7517721513b801dff4ba3f98ef816a240/setproctitle-1.3.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7c5bfe4228ea22373e3025965d1a4116097e555ee3436044f5c954a5e63ac45", size = 35589, upload-time = "2025-09-05T12:50:34.13Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/4f/9f6b2a7417fd45673037554021c888b31247f7594ff4bd2239918c5cd6d0/setproctitle-1.3.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:585edf25e54e21a94ccb0fe81ad32b9196b69ebc4fc25f81da81fb8a50cca9e4", size = 37698, upload-time = "2025-09-05T12:50:35.524Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/92/927b7d4744aac214d149c892cb5fa6dc6f49cfa040cb2b0a844acd63dcaf/setproctitle-1.3.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:96c38cdeef9036eb2724c2210e8d0b93224e709af68c435d46a4733a3675fee1", size = 34201, upload-time = "2025-09-05T12:50:36.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/0c/fd4901db5ba4b9d9013e62f61d9c18d52290497f956745cd3e91b0d80f90/setproctitle-1.3.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:45e3ef48350abb49cf937d0a8ba15e42cee1e5ae13ca41a77c66d1abc27a5070", size = 35801, upload-time = "2025-09-05T12:50:38.314Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/e3/54b496ac724e60e61cc3447f02690105901ca6d90da0377dffe49ff99fc7/setproctitle-1.3.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1fae595d032b30dab4d659bece20debd202229fce12b55abab978b7f30783d73", size = 33958, upload-time = "2025-09-05T12:50:39.841Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/a8/c84bb045ebf8c6fdc7f7532319e86f8380d14bbd3084e6348df56bdfe6fd/setproctitle-1.3.7-cp314-cp314t-win32.whl", hash = "sha256:02432f26f5d1329ab22279ff863c83589894977063f59e6c4b4845804a08f8c2", size = 12745, upload-time = "2025-09-05T12:50:41.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/b6/3a5a4f9952972791a9114ac01dfc123f0df79903577a3e0a7a404a695586/setproctitle-1.3.7-cp314-cp314t-win_amd64.whl", hash = "sha256:cbc388e3d86da1f766d8fc2e12682e446064c01cea9f88a88647cfe7c011de6a", size = 13469, upload-time = "2025-09-05T12:50:42.67Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/8a/aff5506ce89bc3168cb492b18ba45573158d528184e8a9759a05a09088a9/setproctitle-1.3.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:eb440c5644a448e6203935ed60466ec8d0df7278cd22dc6cf782d07911bcbea6", size = 12654, upload-time = "2025-09-05T12:51:17.141Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/89/5b6f2faedd6ced3d3c085a5efbd91380fb1f61f4c12bc42acad37932f4e9/setproctitle-1.3.7-pp310-pypy310_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:502b902a0e4c69031b87870ff4986c290ebbb12d6038a70639f09c331b18efb2", size = 14284, upload-time = "2025-09-05T12:51:18.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/c0/4312fed3ca393a29589603fd48f17937b4ed0638b923bac75a728382e730/setproctitle-1.3.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f6f268caeabb37ccd824d749e7ce0ec6337c4ed954adba33ec0d90cc46b0ab78", size = 13282, upload-time = "2025-09-05T12:51:19.703Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/5b/5e1c117ac84e3cefcf8d7a7f6b2461795a87e20869da065a5c087149060b/setproctitle-1.3.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b1cac6a4b0252b8811d60b6d8d0f157c0fdfed379ac89c25a914e6346cf355a1", size = 12587, upload-time = "2025-09-05T12:51:21.195Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/02/b9eadc226195dcfa90eed37afe56b5dd6fa2f0e5220ab8b7867b8862b926/setproctitle-1.3.7-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f1704c9e041f2b1dc38f5be4552e141e1432fba3dd52c72eeffd5bc2db04dc65", size = 14286, upload-time = "2025-09-05T12:51:22.61Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/26/1be1d2a53c2a91ec48fa2ff4a409b395f836798adf194d99de9c059419ea/setproctitle-1.3.7-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b08b61976ffa548bd5349ce54404bf6b2d51bd74d4f1b241ed1b0f25bce09c3a", size = 13282, upload-time = "2025-09-05T12:51:24.094Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.9.0"
|
||||
@@ -5044,6 +5238,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/be/72/2db2f49247d0a18b4f1bb9a5a39a0162869acf235f3a96418363947b3d46/starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659", size = 73736, upload-time = "2025-09-13T08:41:03.869Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sympy"
|
||||
version = "1.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mpmath", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabulate"
|
||||
version = "0.9.0"
|
||||
@@ -5094,6 +5300,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "2.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/10/56/d7d66a84f96d804155f6ff2873d065368b25a07222a6fd51c4f24ef6d764/termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a", size = 12664, upload-time = "2023-12-01T11:04:51.66Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/5f/8c716e47b3a50cbd7c146f45881e11d9414def768b7cd9c5e6650ec2a80a/termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63", size = 7719, upload-time = "2023-12-01T11:04:50.019Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "threadpoolctl"
|
||||
version = "3.6.0"
|
||||
@@ -5561,6 +5776,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "werkzeug"
|
||||
version = "3.1.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925, upload-time = "2024-11-08T15:52:18.093Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wheel"
|
||||
version = "0.45.1"
|
||||
|
||||
Reference in New Issue
Block a user