Skip to content

Commit a1e8fed

Browse files
cursoragentdhuang
andcommitted
Add User-Agent header to Fireworks API requests
Co-authored-by: dhuang <dhuang@fireworks.ai>
1 parent c3de2a2 commit a1e8fed

File tree

10 files changed

+66
-11
lines changed

10 files changed

+66
-11
lines changed

eval_protocol/adapters/fireworks_tracing.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import os
1313

1414
from eval_protocol.models import EvaluationRow, InputMetadata, ExecutionMetadata, Message
15+
from eval_protocol.common_utils import get_user_agent
1516
from .base import BaseAdapter
1617
from .utils import extract_messages_from_data
1718

@@ -273,7 +274,10 @@ def search_logs(self, tags: List[str], limit: int = 100, hours_back: int = 24) -
273274
if not tags:
274275
raise ValueError("At least one tag is required to fetch logs")
275276

276-
headers = {"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}"}
277+
headers = {
278+
"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}",
279+
"User-Agent": get_user_agent(),
280+
}
277281
params: Dict[str, Any] = {"tags": tags, "limit": limit, "hours_back": hours_back, "program": "eval_protocol"}
278282

279283
# Try /logs first, fall back to /v1/logs if not found
@@ -398,7 +402,10 @@ def get_evaluation_rows(
398402
else:
399403
url = f"{self.base_url}/v1/traces/pointwise"
400404

401-
headers = {"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}"}
405+
headers = {
406+
"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}",
407+
"User-Agent": get_user_agent(),
408+
}
402409

403410
result = None
404411
try:

eval_protocol/auth.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import requests
88

9+
from .common_utils import get_user_agent
10+
911
logger = logging.getLogger(__name__)
1012

1113
# Default locations (used for tests and as fallback). Actual resolution is dynamic via _get_auth_ini_file().
@@ -243,7 +245,7 @@ def verify_api_key_and_get_account_id(
243245
return None
244246
resolved_base = api_base or get_fireworks_api_base()
245247
url = f"{resolved_base.rstrip('/')}/verifyApiKey"
246-
headers = {"Authorization": f"Bearer {resolved_key}"}
248+
headers = {"Authorization": f"Bearer {resolved_key}", "User-Agent": get_user_agent()}
247249
resp = requests.get(url, headers=headers, timeout=10)
248250
if resp.status_code != 200:
249251
logger.debug("verifyApiKey returned status %s", resp.status_code)

eval_protocol/common_utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
import requests
66

77

8+
def get_user_agent() -> str:
9+
"""
10+
Returns the user-agent string for eval-protocol CLI requests.
11+
12+
Format: eval-protocol-cli/{version}
13+
14+
Returns:
15+
User-agent string identifying the eval-protocol CLI and version.
16+
"""
17+
try:
18+
from . import __version__
19+
return f"eval-protocol-cli/{__version__}"
20+
except Exception:
21+
return "eval-protocol-cli/unknown"
22+
23+
824
def load_jsonl(file_path: str) -> List[Dict[str, Any]]:
925
"""
1026
Reads a JSONL file where each line is a valid JSON object and returns a list of these objects.

eval_protocol/evaluation.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
get_fireworks_api_key,
2121
verify_api_key_and_get_account_id,
2222
)
23+
from eval_protocol.common_utils import get_user_agent
2324
from eval_protocol.typed_interface import EvaluationMode
2425

2526
from eval_protocol.get_pep440_version import get_pep440_version
@@ -405,6 +406,7 @@ def preview(self, sample_file, max_samples=5):
405406
headers = {
406407
"Authorization": f"Bearer {auth_token}",
407408
"Content-Type": "application/json",
409+
"User-Agent": get_user_agent(),
408410
}
409411
logger.info(f"Previewing evaluator using API endpoint: {url} with account: {account_id}")
410412
logger.debug(f"Preview API Request URL: {url}")
@@ -748,6 +750,7 @@ def create(self, evaluator_id, display_name=None, description=None, force=False)
748750
headers = {
749751
"Authorization": f"Bearer {auth_token}",
750752
"Content-Type": "application/json",
753+
"User-Agent": get_user_agent(),
751754
}
752755

753756
self._ensure_requirements_present(os.getcwd())

eval_protocol/fireworks_rft.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import requests
1212

1313
from .auth import get_fireworks_account_id, get_fireworks_api_base, get_fireworks_api_key
14+
from .common_utils import get_user_agent
1415

1516

1617
def _map_api_host_to_app_host(api_base: str) -> str:
@@ -157,7 +158,11 @@ def create_dataset_from_jsonl(
157158
display_name: Optional[str],
158159
jsonl_path: str,
159160
) -> Tuple[str, Dict[str, Any]]:
160-
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
161+
headers = {
162+
"Authorization": f"Bearer {api_key}",
163+
"Content-Type": "application/json",
164+
"User-Agent": get_user_agent(),
165+
}
161166
# Count examples quickly
162167
example_count = 0
163168
with open(jsonl_path, "r", encoding="utf-8") as f:
@@ -181,7 +186,7 @@ def create_dataset_from_jsonl(
181186
upload_url = f"{api_base.rstrip('/')}/v1/accounts/{account_id}/datasets/{dataset_id}:upload"
182187
with open(jsonl_path, "rb") as f:
183188
files = {"file": f}
184-
up_headers = {"Authorization": f"Bearer {api_key}"}
189+
up_headers = {"Authorization": f"Bearer {api_key}", "User-Agent": get_user_agent()}
185190
up_resp = requests.post(upload_url, files=files, headers=up_headers, timeout=600)
186191
if up_resp.status_code not in (200, 201):
187192
raise RuntimeError(f"Dataset upload failed: {up_resp.status_code} {up_resp.text}")
@@ -195,7 +200,12 @@ def create_reinforcement_fine_tuning_job(
195200
body: Dict[str, Any],
196201
) -> Dict[str, Any]:
197202
url = f"{api_base.rstrip('/')}/v1/accounts/{account_id}/reinforcementFineTuningJobs"
198-
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json", "Accept": "application/json"}
203+
headers = {
204+
"Authorization": f"Bearer {api_key}",
205+
"Content-Type": "application/json",
206+
"Accept": "application/json",
207+
"User-Agent": get_user_agent(),
208+
}
199209
resp = requests.post(url, json=body, headers=headers, timeout=60)
200210
if resp.status_code not in (200, 201):
201211
raise RuntimeError(f"RFT job creation failed: {resp.status_code} {resp.text}")

eval_protocol/generation/clients.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from omegaconf import DictConfig
1414
from pydantic import BaseModel # Added for new models
1515

16+
from ..common_utils import get_user_agent
17+
1618
logger = logging.getLogger(__name__)
1719

1820

@@ -101,6 +103,7 @@ async def generate(
101103
"Authorization": f"Bearer {self.api_key}",
102104
"Content-Type": "application/json",
103105
"Accept": "application/json",
106+
"User-Agent": get_user_agent(),
104107
}
105108

106109
debug_payload_log = json.loads(json.dumps(payload))

eval_protocol/log_utils/fireworks_tracing_http_handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import requests
88

9+
from ..common_utils import get_user_agent
10+
911

1012
class FireworksTracingHttpHandler(logging.Handler):
1113
"""Logging handler that posts structured logs to tracing.fireworks gateway /logs endpoint."""
@@ -22,7 +24,10 @@ def __init__(self, gateway_base_url: Optional[str] = None, rollout_id_env: str =
2224
api_key = os.environ.get("FIREWORKS_API_KEY")
2325
if api_key:
2426
try:
25-
self._session.headers.update({"Authorization": f"Bearer {api_key}"})
27+
self._session.headers.update({
28+
"Authorization": f"Bearer {api_key}",
29+
"User-Agent": get_user_agent(),
30+
})
2631
except Exception:
2732
pass
2833

eval_protocol/platform_api.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
get_fireworks_api_base,
1212
get_fireworks_api_key,
1313
)
14+
from eval_protocol.common_utils import get_user_agent
1415

1516
logger = logging.getLogger(__name__)
1617

@@ -95,6 +96,7 @@ def create_or_update_fireworks_secret(
9596
headers = {
9697
"Authorization": f"Bearer {resolved_api_key}",
9798
"Content-Type": "application/json",
99+
"User-Agent": get_user_agent(),
98100
}
99101

100102
# The secret_id for GET/PATCH/DELETE operations is the key_name.
@@ -217,7 +219,7 @@ def get_fireworks_secret(
217219
logger.error("Missing Fireworks API key, base URL, or account ID for getting secret.")
218220
return None
219221

220-
headers = {"Authorization": f"Bearer {resolved_api_key}"}
222+
headers = {"Authorization": f"Bearer {resolved_api_key}", "User-Agent": get_user_agent()}
221223
resource_id = _normalize_secret_resource_id(key_name)
222224
url = f"{resolved_api_base.rstrip('/')}/v1/accounts/{resolved_account_id}/secrets/{resource_id}"
223225

@@ -254,7 +256,7 @@ def delete_fireworks_secret(
254256
logger.error("Missing Fireworks API key, base URL, or account ID for deleting secret.")
255257
return False
256258

257-
headers = {"Authorization": f"Bearer {resolved_api_key}"}
259+
headers = {"Authorization": f"Bearer {resolved_api_key}", "User-Agent": get_user_agent()}
258260
resource_id = _normalize_secret_resource_id(key_name)
259261
url = f"{resolved_api_base.rstrip('/')}/v1/accounts/{resolved_account_id}/secrets/{resource_id}"
260262

eval_protocol/pytest/handle_persist_flow.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import re
88
from typing import Any
99

10+
from eval_protocol.common_utils import get_user_agent
1011
from eval_protocol.directory_utils import find_eval_protocol_dir
1112
from eval_protocol.models import EvaluationRow
1213
from eval_protocol.pytest.store_experiment_link import store_experiment_link
@@ -127,7 +128,11 @@ def get_auth_value(key: str) -> str | None:
127128
)
128129
continue
129130

130-
headers = {"Authorization": f"Bearer {fireworks_api_key}", "Content-Type": "application/json"}
131+
headers = {
132+
"Authorization": f"Bearer {fireworks_api_key}",
133+
"Content-Type": "application/json",
134+
"User-Agent": get_user_agent(),
135+
}
131136

132137
# Make dataset first
133138
dataset_url = f"https://api.fireworks.ai/v1/accounts/{fireworks_account_id}/datasets"
@@ -160,7 +165,7 @@ def get_auth_value(key: str) -> str | None:
160165
upload_url = (
161166
f"https://api.fireworks.ai/v1/accounts/{fireworks_account_id}/datasets/{dataset_id}:upload"
162167
)
163-
upload_headers = {"Authorization": f"Bearer {fireworks_api_key}"}
168+
upload_headers = {"Authorization": f"Bearer {fireworks_api_key}", "User-Agent": get_user_agent()}
164169

165170
with open(exp_file, "rb") as f:
166171
files = {"file": f}

eval_protocol/reward_function.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import requests
1111

12+
from .common_utils import get_user_agent
1213
from .models import EvaluateResult, MetricResult
1314
from .typed_interface import reward_function
1415

@@ -211,6 +212,7 @@ def __call__(
211212
headers = {
212213
"Content-Type": "application/json",
213214
"Authorization": f"Bearer {api_key}" if api_key else "",
215+
"User-Agent": get_user_agent(),
214216
}
215217

216218
try:

0 commit comments

Comments
 (0)