Repository navigation
Expand file tree
/
Copy pathtest_mistral_batch_e2e.py
More file actions
140 lines (114 loc) · 4.46 KB
/
Copy pathtest_mistral_batch_e2e.py
File metadata and controls
140 lines (114 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""Live end-to-end test for the Mistral batch path.
The operator gate for the Mistral adapter (status board: "Live Mistral e2e =
future operator gate"). The unit suite proves translation + wiring against mocked
SDK calls; THIS test proves the real round-trip against Mistral's live batch API.
Opt-in and billable. Runs only when ALL of:
- the ``mistral`` extra is installed (``mistralai`` importable);
- ``MISTRAL_API_KEY`` is set;
- ``AIRLOCK_LIVE_MISTRAL_E2E=1`` (explicit opt-in).
It drives the real ``airlock.batch.gateway`` functions against a real
``MistralBackend`` + temp ``BatchStore`` (create -> upload -> create job -> poll
-> fetch -> stage), mirroring ``test_aistudio_batch_e2e.py``.
"""
from __future__ import annotations
import asyncio
import json
import os
import uuid
import pytest
pytestmark = pytest.mark.live
pytest.importorskip("mistralai", reason="mistral extra not installed")
_API_KEY = os.getenv("MISTRAL_API_KEY")
_OPT_IN = os.getenv("AIRLOCK_LIVE_MISTRAL_E2E") == "1"
requires_live = pytest.mark.skipif(
not (_API_KEY and _OPT_IN),
reason="set MISTRAL_API_KEY and AIRLOCK_LIVE_MISTRAL_E2E=1 to run this billable test",
)
_MODEL = os.getenv("AIRLOCK_MISTRAL_E2E_MODEL", "mistral-small-latest")
_TIMEOUT = float(os.getenv("AIRLOCK_MISTRAL_E2E_TIMEOUT", "1500"))
_POLL = float(os.getenv("AIRLOCK_MISTRAL_E2E_POLL", "20"))
_TERMINAL = {"completed", "failed", "expired", "cancelled"}
def _input_lines(alias: str) -> list[dict]:
return [
{
"custom_id": "e2e-pong",
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": alias,
"messages": [
{"role": "system", "content": "You are a terse echo bot."},
{"role": "user", "content": "Reply with exactly one word: PONG"},
],
"temperature": 0,
"max_tokens": 16,
},
},
{
"custom_id": "e2e-math",
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": alias,
"messages": [
{
"role": "user",
"content": "What is 2+2? Reply with just the number.",
},
],
"temperature": 0,
"max_tokens": 16,
},
},
]
def _content(body: dict) -> str:
return body["response"]["body"]["choices"][0]["message"]["content"]
@requires_live
async def test_mistral_batch_full_lifecycle(tmp_path):
from airlock.batch import gateway
from airlock.batch.mistral import MistralBackend
from airlock.batch.store import BatchStore
store = BatchStore(db_path=str(tmp_path / "batch.db"))
backend = MistralBackend(api_key=_API_KEY, provider_model=_MODEL)
alias = "mistral-batch-e2e"
lines = _input_lines(alias)
jsonl = ("\n".join(json.dumps(line) for line in lines)).encode("utf-8")
input_file_id = f"file-e2e-{uuid.uuid4().hex}"
created = await gateway.create_batch(
store,
backend,
input_file_id=input_file_id,
model=alias,
endpoint="/v1/chat/completions",
params=None,
jsonl=jsonl,
client="mistral-e2e",
)
batch_id = created["id"]
print(f"\n[e2e] model={_MODEL} batch_id={batch_id} status={created['status']}")
assert created["status"] in ("validating", "in_progress"), created
obj = created
waited = 0.0
while obj["status"] not in _TERMINAL:
if waited >= _TIMEOUT:
pytest.fail(
f"batch {batch_id} did not finish within {_TIMEOUT}s "
f"(last status {obj['status']})"
)
await asyncio.sleep(_POLL)
waited += _POLL
obj = await gateway.get_batch(store, backend, batch_id)
print(f"[e2e] +{int(waited)}s status={obj['status']}")
assert obj["status"] == "completed", (
f"batch ended {obj['status']}: {obj.get('errors')}"
)
bodies = store.staged_bodies(batch_id)
by_id = {b["custom_id"]: b for b in bodies}
print(f"[e2e] staged custom_ids={sorted(by_id)}")
assert set(by_id) == {"e2e-pong", "e2e-math"}, by_id
pong = by_id["e2e-pong"]
assert pong["error"] is None, pong["error"]
assert "PONG" in _content(pong).upper(), _content(pong)
math = by_id["e2e-math"]
assert math["error"] is None, math["error"]
assert "4" in _content(math), _content(math)