11import atexit
2+ import json
23from typing import Any
34from typing import Dict
45from typing import List
2526from ddtrace .internal .utils .retry import fibonacci_backoff_with_jitter
2627from ddtrace .llmobs import _telemetry as telemetry
2728from ddtrace .llmobs ._constants import AGENTLESS_EVAL_BASE_URL
29+ from ddtrace .llmobs ._constants import AGENTLESS_EXP_BASE_URL
2830from ddtrace .llmobs ._constants import AGENTLESS_SPAN_BASE_URL
2931from ddtrace .llmobs ._constants import DROPPED_IO_COLLECTION_ERROR
3032from ddtrace .llmobs ._constants import DROPPED_VALUE_TEXT
3840from ddtrace .llmobs ._constants import SPAN_SUBDOMAIN_NAME
3941from ddtrace .llmobs ._experiment import Dataset
4042from ddtrace .llmobs ._experiment import DatasetRecord
43+ from ddtrace .llmobs ._experiment import JSONType
4144from ddtrace .llmobs ._utils import safe_json
4245from ddtrace .settings ._agent import config as agent_config
4346
@@ -270,57 +273,73 @@ def _data(self, events: List[LLMObsEvaluationMetricEvent]) -> Dict[str, Any]:
270273
271274class LLMObsExperimentsClient (BaseLLMObsWriter ):
272275
273- def request (self , method : str , path : str , body : bytes = b"" ) -> Response :
276+ AGENTLESS_BASE_URL = AGENTLESS_EXP_BASE_URL
277+
278+ def request (self , method : str , path : str , body : JSONType = None ) -> Response :
274279 headers = {
275280 "Content-Type" : "application/json" ,
276281 "DD-API-KEY" : self ._api_key ,
277282 "DD-APPLICATION-KEY" : self ._app_key ,
278283 }
279- site = self ._site
280- if site == "datad0g.com" :
281- base = "https://dd.datad0g.com"
282- else :
283- base = f"https://api.{ site } "
284-
285- conn = get_connection (base )
284+ body = json .dumps (body ).encode ("utf-8" ) if body else b""
285+ conn = get_connection (self ._intake )
286286 try :
287- url = base + path
287+ url = self . _intake + path
288288 logger .debug ("requesting %s" , url )
289289 conn .request (method , url , body , headers )
290290 resp = conn .getresponse ()
291- if resp .status >= 300 :
292- raise ValueError (f"Failed to { method } { path } : { resp .status } " )
293291 return Response .from_http_response (resp )
294292 finally :
295293 conn .close ()
296294
297- def dataset_pull (self , name : str ) -> Dataset :
295+ def dataset_delete (self , dataset_id : str ) -> None :
296+ path = "/api/unstable/llm-obs/v1/datasets/delete"
297+ resp = self .request ("POST" , path , body = {
298+ "data" : {
299+ "type" : "datasets" ,
300+ "attributes" : {
301+ "type" : "soft" ,
302+ "dataset_ids" : [dataset_id ],
303+ },
304+ },
305+ })
306+ assert resp .status == 200 , f"Failed to delete dataset { id } : { resp .get_json ()} "
307+ return None
308+
309+ def dataset_create (self , name : str , description : str ) -> Dataset :
310+ path = "/api/unstable/llm-obs/v1/datasets"
311+ body = {
312+ "data" : {
313+ "type" : "datasets" ,
314+ "attributes" : {"name" : name , "description" : description },
315+ }
316+ }
317+ resp = self .request ("POST" , path , body )
318+ response_data = resp .get_json ()
319+ dataset_id = response_data ["data" ]["id" ]
320+ return Dataset (name , dataset_id , [])
298321
322+ def dataset_pull (self , name : str ) -> Dataset :
299323 path = f"/api/unstable/llm-obs/v1/datasets?filter[name]={ quote (name )} "
300324 resp = self .request ("GET" , path )
301325
302326 response_data = resp .get_json ()
303- datasets = response_data .get ("data" , [])
304-
305- if not datasets :
327+ data = response_data ["data" ]
328+ if not data :
306329 raise ValueError (f"Dataset '{ name } ' not found" )
307330
308- dataset_id = datasets [0 ]["id" ]
331+ dataset_id = data [0 ]["id" ]
309332 url = f"/api/unstable/llm-obs/v1/datasets/{ dataset_id } /records"
310- try :
311- resp = self .request ("GET" , url )
312- records_data = resp .get_json ()
313- except ValueError as e :
314- if "404" in str (e ):
315- raise ValueError (f"Dataset '{ name } ' not found" ) from e
316- raise
333+ resp = self .request ("GET" , url )
334+ if resp .status == 404 :
335+ raise ValueError (f"Dataset '{ name } ' not found" )
336+ records_data = resp .get_json ()
317337
318338 class_records : List [DatasetRecord ] = []
319339 for record in records_data .get ("data" , []):
320340 attrs = record .get ("attributes" , {})
321341 input_data = attrs .get ("input" )
322342 expected_output = attrs .get ("expected_output" )
323-
324343 class_records .append (
325344 {
326345 "record_id" : record .get ("id" ),
@@ -329,7 +348,6 @@ def dataset_pull(self, name: str) -> Dataset:
329348 ** attrs .get ("metadata" , {}),
330349 }
331350 )
332-
333351 return Dataset (name , dataset_id , class_records )
334352
335353
0 commit comments