def add_generation(self, langfuse_generation_data: LangfuseGeneration | None = None): data = filter_none_values(langfuse_generation_data.model_dump()) if langfuse_generation_data else {} try: usage_data = data.pop("usage", None) usage = None if usage_data: usage = Usage( input=usage_data.get("input", 0) or 0, output=usage_data.get("output", 0) or 0, total=usage_data.get("total", 0) or 0, unit=usage_data.get("unit"), input_cost=usage_data.get("inputCost"), output_cost=usage_data.get("outputCost"), total_cost=usage_data.get("totalCost"), ) # Langfuse v4 requires observation body.id; auto-assign if missing if not data.get("id"): data["id"] = str(uuid.uuid4()) body = CreateGenerationBody( id=data.get("id"), trace_id=data.get("trace_id"), name=data.get("name"), start_time=data.get("start_time"), end_time=data.get("end_time"), model=data.get("model"), model_parameters=data.get("model_parameters"), input=data.get("input"), output=data.get("output"), usage=usage, metadata=data.get("metadata"), level=data.get("level"), status_message=data.get("status_message"), parent_observation_id=data.get("parent_observation_id"), version=data.get("version"), completion_start_time=data.get("completion_start_time"), ) event = IngestionEvent_GenerationCreate( body=body, id=self._make_event_id(), timestamp=self._now_iso(), ) self.langfuse_client.api.ingestion.batch(batch=[event]) logger.debug("LangFuse Generation created successfully") except Exception as e: raise ValueError(f"LangFuse Failed to create generation: {str(e)}")