Track OpenAI, Claude, Gemini and OpenAI-compatible models then give solutions to improve your agent system.
Project description
mwin
mwin: Track OpenAI, Claude, Gemini and OpenAI-compatible models then give solutions to improve your agent system.
Our goal is to make llm application more valuable and effortlessly improve llm capabilities.
Quickstart
You can use pip install mwin
pip install mwin
OR pip install from source.
git clone https://github.com/yanghui1-arch/mwin.git
cd src
pip install -e .
Then you need to configure mwin through CLI.
mwin configure
Then you just follow the instructions to configure mwin.
> Which deployment type do you choose?
> 1 - mwin Cloud Platform (default)
> 2 - mwin Local Platform
> Please input the choice number.>2
> Please enter your API key:
> What's your project name? mwin-demo
> Congrats to configure mwin.
It needs an Mwin API key. You can get the apikey after logging http://localhost:5173.
Finally use @track to track your llm input and output.
The simplest Demo
from mwin import track
from openai import OpenAI
openai_apikey = "<llm_api_key>"
openai_base_url = "<llm_base_url>"
model = "<llm_model>"
@track()
def run_agent(prompt: str):
cli = OpenAI(base_url=openai_base_url, api_key=openai_apikey)
content = cli.chat.completions.create(
messages=[{"role": "user", "content": f"{prompt}"}],
model=model
).choices[0].message.content
return content
run_agent("hello, mwin.")
Using start_trace() to manually set the trace scope
It's the most recommended method to use mwin to track the trace in a project. mwin offers two context manager to make trace scope more clear. It's very easy to use and not breaking change your current project code. Using start_trace_async() for async context manager. The usage of them is both same.
Demo
from mwin import track, start_trace
from openai import OpenAI
openai_apikey = "<llm_api_key>"
openai_base_url = "<llm_base_url>"
model = "<llm_model>"
@track(step_type="tool")
def execute_bash(command: str):
# assume execute bash and get a stdout
return "<bash_stdout>"
@track()
def run_agent(prompt: str):
cli = OpenAI(base_url=openai_base_url, api_key=openai_apikey)
content = cli.chat.completions.create(
messages=[{"role": "user", "content": f"{prompt}"}],
model=model
).choices[0].message.content
if "bash" in content:
res = execute_bash(content)
return res
return content
@track()
def query_for_information(stmt: str) -> str:
...
with start_trace():
info = query_for_information("mwin")
run_agent()
Using mwin with Thread Pools
If you are using with start_trace() or async with start_trace_async() Skip this part.
When your program uses ThreadPoolExecutor, multiprocessing.pool.ThreadPool, or similar thread pools, and you wouldn't like to use start_trace() and start_trace_async() you have to be aware of how mwin traces work with thread reuse.
The correct solution is to use contextvars.copy_context(). Wrap your submitted task with copy_context().run() to give each task an isolated context. The trace is probably record unexpectedly without contextvars.copy_context().
import contextvars
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=10)
# Without fix — trace leaks between tasks on the same thread
executor.submit(run_agent)
# With fix — each task gets a clean, isolated context
ctx = contextvars.copy_context()
executor.submit(ctx.run, run_agent)
ctx.run(run_agent) creates a context sandbox: all ContextVar operations inside it go to ctx, not to the thread's persistent context. When ctx.run() returns, ctx is garbage collected along with its trace.
Example: FastAPI with ThreadPoolExecutor
import asyncio
import contextvars
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(max_workers=10)
@app.post("/chat")
async def chat_handler(request: Request):
loop = asyncio.get_running_loop()
def run_agent():
agent_step_1() # @track — creates trace, shares it
agent_step_2() # @track — reuses same trace
agent_step_3() # @track — reuses same trace
ctx = contextvars.copy_context()
loop.run_in_executor(executor, ctx.run, run_agent)
Conditions you have to notice
| Scenario | Action needed |
|---|---|
| scripts | None |
| Celery tasks | None (auto-handled) |
| fastapi using async not sync | None |
threading.Thread |
None |
ThreadPoolExecutor |
Use copy_context().run() |
asyncio.loop.run_in_executor |
Use copy_context().run() |
multiprocessing.pool.ThreadPool |
Use copy_context().run() |
ProcessPoolExecutor |
None (separate processes) |
Development
Mwin project package manager is uv. If you are a beginner uver, please click uv link: uv official link
uv sync
uv .venv/Script/activate
You can watch more detailed debug information by using --log-level=DEBUG or set AT_LOG_LEVEL=DEBUG for Windows or export AT_LOG_LEVEL=DEBUG for Linux and Mac.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mwin-0.2.3.tar.gz.
File metadata
- Download URL: mwin-0.2.3.tar.gz
- Upload date:
- Size: 38.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
368ad3ad1398f1f01afa4a05489d9ff45a06a5c5669fbe8289204220df77c4ce
|
|
| MD5 |
cd2b5eefbf2a43945b23c0ca8623b486
|
|
| BLAKE2b-256 |
5c428898280faa28f54dd02fd1221d073647a5eed81a061b4a51cfb9016a6394
|
File details
Details for the file mwin-0.2.3-py3-none-any.whl.
File metadata
- Download URL: mwin-0.2.3-py3-none-any.whl
- Upload date:
- Size: 47.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
107c50f3f94a7a4beec5671bfecc8400c0dbc7c6af9954598eefcd0567662d23
|
|
| MD5 |
4981a56ac8d87cc2bb177707a635885f
|
|
| BLAKE2b-256 |
2e22c32032fa35996e417c233da849ebea1cc2b9dc4039ac6d15956fa781d543
|