Skip to content

Commit d21f015

Browse files
authored
Merge pull request #56 from Flemington8/main
Add new clients and update README with usage instructions
2 parents c7edeae + 2b41afd commit d21f015

12 files changed

+4285
-944
lines changed

clients/README.md

+58-5
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,75 @@ These clients are some baselines that we have implemented and evaluated to help
55

66
## Clients
77

8-
- [GPT](/clients/gpt.py): A naive GPT4-based LLM agent with only shell access.
8+
- [GPT](/clients/gpt.py): A naive GPT series LLM agent with only shell access.
9+
- [DeepSeek](/clients/deepseek.py): A naive DeepSeek series LLM agent with only shell access.
10+
- [Qwen](/clients/qwen.py): A naive Qwen series LLM agent with only shell access.
11+
- [vLLM](/clients/vllm.py): A naive vLLM agent with any open source LLM deployed locally and only shell access.
912
- [ReAct](/clients/react.py): A naive LLM agent that uses the ReAct framework.
1013
- [FLASH](/clients/flash.py): A naive LLM agent that uses status supervision and hindsight integration components to ensure the high reliability of workflow execution.
1114

15+
### Using the vLLM Client
16+
17+
The vLLM client allows you to run local open-source models as an agent for AIOpsLab tasks. This approach is particularly useful when you want to:
18+
- Use your own hardware for inference
19+
- Experiment with different open-source models
20+
- Work in environments without internet access to cloud LLM providers
21+
22+
### Quick Setup Guide
23+
24+
1. **Launch the vLLM server**:
25+
```bash
26+
# Make the script executable
27+
chmod +x ./clients/launch_vllm.sh
28+
29+
# Run the script
30+
./clients/launch_vllm.sh
31+
```
32+
This will launch vLLM in the background using the default model (Qwen/Qwen2.5-3B-Instruct).
33+
34+
2. **Check server status**:
35+
```bash
36+
# View the log file to confirm the server is running
37+
cat vllm_Qwen_Qwen2.5-3B-Instruct.log
38+
```
39+
40+
3. **Customize the model** (optional):
41+
Edit `launch_vllm.sh` to change the model:
42+
```bash
43+
# Open the file
44+
nano ./clients/launch_vllm.sh
45+
46+
# Change the MODEL variable to your preferred model
47+
# Example: MODEL="mistralai/Mistral-7B-Instruct-v0.1"
48+
```
49+
50+
4. **Run the vLLM agent**:
51+
```
52+
python clients/vllm.py
53+
```
54+
55+
### Requirements
56+
57+
- Poetry for dependency management
58+
- Sufficient GPU resources for your chosen model
59+
- The model must support the OpenAI chat completion API format
60+
61+
### Advanced Configuration
62+
63+
The vLLM client connects to `http://localhost:8000/v1` by default. If you've configured vLLM to use a different port or host, update the base_url in `clients/utils/llm.py` in the vLLMClient class.
64+
1265
<!--
1366
Note: The script [GPT-managed-identity](/clients/gpt_managed_identity.py) uses the `DefaultAzureCredential` method from the `azure-identity` package to authenticate. This method simplifies authentication by supporting various credential types, including managed identities.
1467
1568
We recommend using a [user-assigned managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-manage-user-assigned-managed-identities?pivots=identity-mi-methods-azp) for this setup. Ensure the following steps are completed:
1669
1770
1. **Role Assignment**: Assign the managed identity appropriate roles:
18-
- A role that provides read access to the VM, such as the built-in **Reader** role.
19-
- A role that grants read/write access to the Azure OpenAI Service, such as the **Azure AI Developer** role.
71+
- A role that provides read access to the VM, such as the built-in **Reader** role.
72+
- A role that grants read/write access to the Azure OpenAI Service, such as the **Azure AI Developer** role.
2073
2174
2. **Attach the Managed Identity to the Controller VM**:
22-
Follow the steps in the official documentation to add the managed identity to the VM:
23-
[Add a user-assigned managed identity to a VM](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities?pivots=qs-configure-portal-windows-vm#user-assigned-managed-identity).
75+
Follow the steps in the official documentation to add the managed identity to the VM:
76+
[Add a user-assigned managed identity to a VM](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities?pivots=qs-configure-portal-windows-vm#user-assigned-managed-identity).
2477
2578
Please ensure the required Azure configuration is provided using the /configs/example_azure_config.yml file, or use it as a template to create a new configuration file
2679

clients/deepseek.py

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Naive DeepSeek-R1 client (with shell access) for AIOpsLab.
2+
3+
"DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning" arXiv preprint arXiv:2501.12948 (2025).
4+
5+
Paper: https://arxiv.org/abs/2501.12948
6+
"""
7+
8+
9+
import os
10+
import asyncio
11+
12+
import wandb
13+
from aiopslab.orchestrator import Orchestrator
14+
from clients.utils.llm import DeepSeekClient
15+
from clients.utils.templates import DOCS_SHELL_ONLY
16+
from dotenv import load_dotenv
17+
18+
load_dotenv()
19+
20+
class Agent:
21+
def __init__(self):
22+
self.history = []
23+
self.llm = DeepSeekClient()
24+
25+
def init_context(self, problem_desc: str, instructions: str, apis: str):
26+
"""Initialize the context for the agent."""
27+
28+
self.shell_api = self._filter_dict(
29+
apis, lambda k, _: "exec_shell" in k)
30+
self.submit_api = self._filter_dict(apis, lambda k, _: "submit" in k)
31+
32+
def stringify_apis(apis): return "\n\n".join(
33+
[f"{k}\n{v}" for k, v in apis.items()]
34+
)
35+
36+
self.system_message = DOCS_SHELL_ONLY.format(
37+
prob_desc=problem_desc,
38+
shell_api=stringify_apis(self.shell_api),
39+
submit_api=stringify_apis(self.submit_api),
40+
)
41+
42+
self.task_message = instructions
43+
44+
self.history.append({"role": "system", "content": self.system_message})
45+
self.history.append({"role": "user", "content": self.task_message})
46+
self.history.append({"role": "assistant", "content": ""}) # Interleave the user/assistant messages in the message sequence.
47+
48+
async def get_action(self, input) -> str:
49+
"""Wrapper to interface the agent with OpsBench.
50+
51+
Args:
52+
input (str): The input from the orchestrator/environment.
53+
54+
Returns:
55+
str: The response from the agent.
56+
"""
57+
self.history.append({"role": "user", "content": input})
58+
response = self.llm.run(self.history)
59+
self.history.append({"role": "assistant", "content": response[0]})
60+
return response[0]
61+
62+
def _filter_dict(self, dictionary, filter_func):
63+
return {k: v for k, v in dictionary.items() if filter_func(k, v)}
64+
65+
66+
if __name__ == "__main__":
67+
# Load use_wandb from environment variable with a default of False
68+
use_wandb = os.getenv("USE_WANDB", "false").lower() == "true"
69+
70+
if use_wandb:
71+
# Initialize wandb running
72+
wandb.init(project="AIOpsLab", entity="AIOpsLab")
73+
74+
agent = Agent()
75+
76+
orchestrator = Orchestrator()
77+
orchestrator.register_agent(agent, name="deepseek-r1")
78+
79+
pid = "misconfig_app_hotel_res-mitigation-1"
80+
problem_desc, instructs, apis = orchestrator.init_problem(pid)
81+
agent.init_context(problem_desc, instructs, apis)
82+
asyncio.run(orchestrator.start_problem(max_steps=10))
83+
84+
if use_wandb:
85+
# Finish the wandb run
86+
wandb.finish()

clients/flash.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
from typing import List, Dict, Tuple, Any
66
from pydantic import BaseModel
7-
from clients.utils.llm import GPT4Turbo
7+
from clients.utils.llm import GPTClient
88
from aiopslab.orchestrator import Orchestrator
99

1010
logging.basicConfig(level=logging.INFO)
@@ -14,7 +14,7 @@
1414
class FlashAgent:
1515
def __init__(self):
1616
self.history = []
17-
self.llm = GPT4Turbo()
17+
self.llm = GPTClient()
1818
self.hindsight_builder = HindsightBuilder()
1919

2020
def init_context(self, problem_desc: str, instructions: str, apis: dict):
@@ -76,7 +76,7 @@ async def diagnose_with_hindsight(self, input: str, history: dict):
7676
class HindsightBuilder:
7777
"""Agent hindsight generator."""
7878

79-
llm = GPT4Turbo()
79+
llm = GPTClient()
8080

8181
def generate_prompt(self, input: str, history: dict) -> str:
8282
"""

clients/gpt.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import wandb
1313
from aiopslab.orchestrator import Orchestrator
14-
from clients.utils.llm import GPT4Turbo
14+
from clients.utils.llm import GPTClient
1515
from clients.utils.templates import DOCS_SHELL_ONLY
1616
from dotenv import load_dotenv
1717

@@ -21,7 +21,7 @@
2121
class Agent:
2222
def __init__(self):
2323
self.history = []
24-
self.llm = GPT4Turbo()
24+
self.llm = GPTClient()
2525

2626
def init_context(self, problem_desc: str, instructions: str, apis: str):
2727
"""Initialize the context for the agent."""

clients/gpt_managed_identity.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Naive GPT4 client (with shell access) for AIOpsLab. Uses Azure Managed Identity for authentication.
1+
"""Naive GPT client (with shell access) for AIOpsLab. Uses Azure Managed Identity for authentication.
22
33
Achiam, Josh, Steven Adler, Sandhini Agarwal, Lama Ahmad, Ilge Akkaya, Florencia Leoni Aleman, Diogo Almeida et al.
44
"Gpt-4 technical report." arXiv preprint arXiv:2303.08774 (2023).
@@ -11,14 +11,14 @@
1111
import asyncio
1212

1313
from aiopslab.orchestrator import Orchestrator
14-
from clients.utils.llm import GPT4Turbo
14+
from clients.utils.llm import GPTClient
1515
from clients.utils.templates import DOCS_SHELL_ONLY
1616

1717

1818
class Agent:
1919
def __init__(self, azure_config_file: str):
2020
self.history = []
21-
self.llm = GPT4Turbo(auth_type="managed", azure_config_file=azure_config_file)
21+
self.llm = GPTClient(auth_type="managed", azure_config_file=azure_config_file)
2222

2323
def init_context(self, problem_desc: str, instructions: str, apis: str):
2424
"""Initialize the context for the agent."""

clients/launch_vllm.sh

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
# This script launches vLLM in the background, redirecting output to a log file.
3+
4+
# Set the model directory/path and desired port
5+
MODEL="Qwen/Qwen2.5-3B-Instruct"
6+
7+
# Create a safe filename by replacing slashes with underscores
8+
SAFE_MODEL_NAME=$(echo $MODEL | tr '/' '_')
9+
10+
# Launch vLLM in background using nohup and redirect both stdout and stderr to a log file.
11+
# nohup poetry run vllm serve $MODEL --tensor-parallel-size 4 > vllm_$SAFE_MODEL_NAME.log 2>&1 &
12+
nohup poetry run vllm serve $MODEL > vllm_$SAFE_MODEL_NAME.log 2>&1 &
13+
14+
# Print a message indicating that vLLM is running.
15+
echo "vLLM has been launched in the background with the $MODEL model. Check vllm_$SAFE_MODEL_NAME.log for output."

clients/qwen.py

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""Naive Qwen client (with shell access) for AIOpsLab.
2+
"""
3+
4+
import os
5+
import asyncio
6+
7+
import wandb
8+
from aiopslab.orchestrator import Orchestrator
9+
from clients.utils.llm import QwenClient
10+
from clients.utils.templates import DOCS_SHELL_ONLY
11+
12+
13+
class Agent:
14+
def __init__(self):
15+
self.history = []
16+
self.llm = QwenClient()
17+
18+
def init_context(self, problem_desc: str, instructions: str, apis: str):
19+
"""Initialize the context for the agent."""
20+
21+
self.shell_api = self._filter_dict(
22+
apis, lambda k, _: "exec_shell" in k)
23+
self.submit_api = self._filter_dict(apis, lambda k, _: "submit" in k)
24+
25+
def stringify_apis(apis): return "\n\n".join(
26+
[f"{k}\n{v}" for k, v in apis.items()]
27+
)
28+
29+
self.system_message = DOCS_SHELL_ONLY.format(
30+
prob_desc=problem_desc,
31+
shell_api=stringify_apis(self.shell_api),
32+
submit_api=stringify_apis(self.submit_api),
33+
)
34+
35+
self.task_message = instructions
36+
37+
self.history.append({"role": "system", "content": self.system_message})
38+
self.history.append({"role": "user", "content": self.task_message})
39+
40+
async def get_action(self, input) -> str:
41+
"""Wrapper to interface the agent with OpsBench.
42+
43+
Args:
44+
input (str): The input from the orchestrator/environment.
45+
46+
Returns:
47+
str: The response from the agent.
48+
"""
49+
self.history.append({"role": "user", "content": input})
50+
response = self.llm.run(self.history)
51+
self.history.append({"role": "assistant", "content": response[0]})
52+
return response[0]
53+
54+
def _filter_dict(self, dictionary, filter_func):
55+
return {k: v for k, v in dictionary.items() if filter_func(k, v)}
56+
57+
58+
if __name__ == "__main__":
59+
# Load use_wandb from environment variable with a default of False
60+
use_wandb = os.getenv("USE_WANDB", "false").lower() == "true"
61+
62+
if use_wandb:
63+
# Initialize wandb running
64+
wandb.init(project="AIOpsLab", entity="AIOpsLab")
65+
66+
agent = Agent()
67+
68+
orchestrator = Orchestrator()
69+
orchestrator.register_agent(agent, name="qwq-32b")
70+
71+
pid = "misconfig_app_hotel_res-mitigation-1"
72+
problem_desc, instructs, apis = orchestrator.init_problem(pid)
73+
agent.init_context(problem_desc, instructs, apis)
74+
asyncio.run(orchestrator.start_problem(max_steps=10))
75+
76+
if use_wandb:
77+
# Finish the wandb run
78+
wandb.finish()

clients/react.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import asyncio
1111

1212
from aiopslab.orchestrator import Orchestrator
13-
from clients.utils.llm import GPT4Turbo
13+
from clients.utils.llm import GPTClient
1414
from clients.utils.templates import DOCS
1515

1616
RESP_INSTR = """DO NOT REPEAT ACTIONS! Respond with:
@@ -22,7 +22,7 @@
2222
class Agent:
2323
def __init__(self):
2424
self.history = []
25-
self.llm = GPT4Turbo()
25+
self.llm = GPTClient()
2626

2727
def init_context(self, problem_desc: str, instructions: str, apis: str):
2828
"""Initialize the context for the agent."""

0 commit comments

Comments
 (0)