Skip to content

Commit 327bde7

Browse files
authored
fix(llmobs): remove base URL checks for LLM Obs integrations (#13580)
This PR reverts the changes from #12457 since we have received many escalations due to customers not seeing their spans appear in LLM Observability when using a non-default base URL. I decided to do this revert manually to avoid confusing conflicts with more recent changes to the integrations. I am opting to do manual testing for this change since functionality should return to what it was before #12457, and I have a PR in progress to implement the remaining portion of this work (allow users to configure their proxy URLs in order to get workflow spans instead of LLM spans for client-side requests directed to a proxy) which will include tests for proxy requests. # Manual Testing ## Anthropic Request with default base URL ([trace](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=false&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7PN0I94T_HgAAABhBWmM3UE4wSUFBRGMxX2RJZ000VUFBQUEAAAAkZjE5NzNiM2MtZjYwMC00Y2Y5LTg2YjEtMWEyOWNiZDdmNjM4AAAJ8w%22%7D%5D&sidepanelTab=trace&spanId=5618139561267282384&start=1749041976715&end=1749045576715&paused=false)). ``` from anthropic import Anthropic client = Anthropic() message = client.messages.create( max_tokens=1024, messages=[ { "role": "user", "content": "What color is the sky?", } ], model="claude-3-5-sonnet-20240620", ) ``` Request with base URL specified ([trace](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7PgZl-CD_HgAAABhBWmM3UGdabEFBQkFWYk9mSVVnZEFBQUEAAAAkMDE5NzNiM2UtMGE0OS00ZDljLWJjZGQtNzBkMDM1MWZlYTVhAAAJhQ%22%7D%5D&sidepanelTab=trace&spanId=12859714686052428327&start=1749044723711&end=1749045623711&paused=false)). ``` from anthropic import Anthropic client = Anthropic( base_url="http://localhost:4000", ) message = client.messages.create( max_tokens=1024, messages=[ { "role": "user", "content": "What color is the sky?", } ], model="claude-3.5", ) ``` ## Bedrock Request with default base URL ([trace](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7P8PE-Sn_HgAAABhBWmM3UDhQRUFBREV6NUdlUnc5QUFBQUEAAAAkZjE5NzNiNDAtMDc5Yi00NTJkLTgwNTYtNmY0NDk0YmYwMWUyAAAJiw%22%7D%5D&sidepanelTab=trace&spanId=9734361671629963740&start=1749044925806&end=1749045825806&paused=false)). ``` import boto3 import json session = boto3.Session(profile_name='601427279990_account-admin', region_name="us-east-1") brt = session.client( service_name='bedrock-runtime', ) modelId = 'amazon.titan-text-lite-v1' accept = 'application/json' contentType = 'application/json' input_text = "Explain black holes to 8th graders." body = { "inputText": input_text, } body = json.dumps(body) response = brt.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType) response_body = json.loads(response.get('body').read()) ``` Request with base URL specified (traces for when server is [instrumented](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=false&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7QSom-fb_HgAAABhBWmM3UVNvbUFBRGpSV3ZJbVJfbkFBQUEAAAAkMDE5NzNiNDEtNDU3Yy00OWI5LWI1ZWItZjg5YmMyYWEyM2QyAAAI7w%22%7D%5D&sidepanelTab=trace&spanId=5082411573978329245&start=1749044950932&end=1749045850932&paused=false) and not [instrumented](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7QtYB2Z5mCAAAABhBWmM3UXRZQkFBQ3JxZkVMa2oxQUFBQUEAAABdMTE5NzNiNDMtMGE1Yi00ZmQzLTlhM2MtYTI1YzE2NzgwNmI1LXN5bnRoZXRpYy10aW1lLTE3NDkwNDIwMDAwMDAwMDAwMDBjLTE3NDkwNDU5Mzg3NzkwMDAwMDFvAAAJ2Q%22%7D%5D&sidepanelTab=trace&spanId=8610037816587948263&start=1749045049165&end=1749045949165&paused=false)). Server Code (I created a proxy server of my own to test this out!) ``` from fastapi import FastAPI, Request import uvicorn import boto3 import json app = FastAPI() @app.post("/model/{model_id}/invoke") async def invoke_model(model_id: str, request: Request): body = await request.json() session = boto3.Session(profile_name='601427279990_account-admin', region_name="us-east-1") brt = session.client( service_name='bedrock-runtime', ) body = json.dumps(body) response = brt.invoke_model(body=body, modelId=request.path_params.get("model_id"), accept=request.headers.get("accept"), contentType=request.headers.get("content-type")) response_body = json.loads(response.get('body').read()) return response_body if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=4000) ``` Client code ``` import boto3 import json session = boto3.Session(profile_name='601427279990_account-admin', region_name="us-east-1") brt = session.client( service_name='bedrock-runtime', endpoint_url="http://0.0.0.0:4000", ) modelId = 'amazon.titan-text-lite-v1' accept = 'application/json' contentType = 'application/json' input_text = "Explain black holes to 8th graders." body = { "inputText": input_text, } body = json.dumps(body) response = brt.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType) response_body = json.loads(response.get('body').read()) ``` ## Langchain Request with default base URL ([trace](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7Th6v-LXdEgAAABhBWmM3VGg2dkFBQmRpN05Hb29rM0FBQUEAAABdMTE5NzNiNGUtMzA2Ni00YmMwLWIzZWQtZDcxNWZhNzc4NTI3LXN5bnRoZXRpYy10aW1lLTE3NDkwNDU2MDAwMDAwMDAwMDBjLTE3NDkwNDY2Njk0MTQwMDAwMDFvAAAAJA%22%7D%5D&sidepanelTab=trace&spanId=10904991825240620648&start=1749045791545&end=1749046691545&paused=false)). ``` from langchain.chat_models import ChatOpenAI from langchain.schema import HumanMessage, SystemMessage chat = ChatOpenAI( model = "gpt-3.5-turbo", temperature=0.1, ) messages = [ SystemMessage( content="You are a helpful assistant that im using to make a test request to." ), HumanMessage( content="test from litellm. tell me why it's amazing in 1 sentence" ), ] response = chat(messages) ``` Request with base URL specified (traces when server is [instrumented](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7TW9rguFD0AAAABhBWmM3VFc5ckFBREZmclJ1MU9TVUFBQUEAAABdMTE5NzNiNGQtNmY4Zi00NjNlLWIxZGUtNmUzYmRiN2I0Y2E0LXN5bnRoZXRpYy10aW1lLTE3NDkwNDU2MDAwMDAwMDAwMDBjLTE3NDkwNDY2MjAwNDcwMDAwMDFvAAAADQ%22%7D%5D&sidepanelTab=trace&spanId=8307880165467569356&start=1749045735409&end=1749046635409&paused=false) and [not instrumented](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=false&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7SHY7M1vhCwAAABhBWmM3U0hZN0FBQnQ0SGJrUUR6TkFBQUEAAABdMDE5NzNiNDgtNzYzZC00NWNhLWI0MTEtMDRmZWNiY2E3NTk5LXN5bnRoZXRpYy10aW1lLTE3NDkwNDIwMDAwMDAwMDAwMDBjLTE3NDkwNDYyOTQwNzcwMDAwMDFvAAAAEw%22%7D%5D&sidepanelTab=trace&spanId=11096434266997811885&start=1749045669054&end=1749046569054&paused=false)). ``` from langchain.chat_models import ChatOpenAI from langchain.schema import HumanMessage, SystemMessage chat = ChatOpenAI( base_url="http://0.0.0.0:4000", model = "gpt-3.5-turbo", temperature=0.1, ) messages = [ SystemMessage( content="You are a helpful assistant that im using to make a test request to." ), HumanMessage( content="test from litellm. tell me why it's amazing in 1 sentence" ), ] response = chat(messages) ``` ## Open AI Request with default base URL ([trace](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7RqRAW_lvvQAAABhBWmM3UnFSQUFBQlUxWGZnS3hqUUFBQUEAAABdMTE5NzNiNDYtYTQ0MC00ODc5LTkyNjQtNzk4MTUyZDNjMWIzLXN5bnRoZXRpYy10aW1lLTE3NDkwNDIwMDAwMDAwMDAwMDBjLTE3NDkwNDYxNzQ3ODQwMDAwMDFvAAAAKQ%22%7D%5D&sidepanelTab=trace&spanId=17834548293768414476&start=1749045289463&end=1749046189463&paused=false)). ``` import os from openai import OpenAI oai_client = OpenAI( api_key=os.environ.get("OPENAI_API_KEY"), ) completion = oai_client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "user", "content": "testing openai"}, ], ) ``` Request with base URL specified (traces when server is [instrumented](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=false&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7RWmuM0bhCwAAABhBWmM3UldtdUFBQU9zWkQtVkdQN0FBQUEAAABdMDE5NzNiNDUtNjlkMC00NjViLTg1NzYtMGUyZGFjMWE2OTUwLXN5bnRoZXRpYy10aW1lLTE3NDkwNDIwMDAwMDAwMDAwMDBjLTE3NDkwNDYwOTQyODgwMDAwMDFvAAAAIg%22%7D%5D&sidepanelTab=trace&spanId=11019904099175727297&start=1749045219049&end=1749046119049&paused=false) and [not instrumented](https://dd.datad0g.com/llm/traces?query=%40ml_app%3Anicole-test%20%40event_type%3Aspan%20%40parent_id%3Aundefined&agg_m=count&agg_m_source=base&agg_t=count&fromUser=true&llmPanels=%5B%7B%22t%22%3A%22sampleDetailPanel%22%2C%22rEID%22%3A%22AwAAAZc7Rn0emfEClAAAABhBWmM3Um4wZUFBQXpZb2NnbzNRTUFBQUEAAABdMTE5NzNiNDYtN2QxZS00MThkLTg4MzItYzVmMDNmNjZkN2YxLXN5bnRoZXRpYy10aW1lLTE3NDkwNDIwMDAwMDAwMDAwMDBjLTE3NDkwNDYxNjQ3NjYwMDAwMDFvAAAARw%22%7D%5D&sidepanelTab=trace&spanId=4955295909966002358&start=1749045278443&end=1749046178443&paused=false)). ``` import os from openai import OpenAI oai_client = OpenAI( api_key=os.environ.get("OPENAI_API_KEY"), base_url="http://0.0.0.0:4000", ) completion = oai_client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "user", "content": "testing openai"}, ], ) ``` ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)
1 parent 7c82763 commit 327bde7

File tree

17 files changed

+16
-685
lines changed

17 files changed

+16
-685
lines changed

ddtrace/contrib/internal/anthropic/patch.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,11 @@ def traced_chat_model_generate(anthropic, pin, func, instance, args, kwargs):
4343
chat_messages = get_argument_value(args, kwargs, 0, "messages")
4444
integration = anthropic._datadog_integration
4545
stream = False
46-
client = getattr(instance, "_client", None)
47-
base_url = getattr(client, "_base_url", None) if client else None
4846

4947
span = integration.trace(
5048
pin,
5149
"%s.%s" % (instance.__class__.__name__, func.__name__),
52-
# only report LLM Obs spans if base_url has not been changed
53-
submit_to_llmobs=integration.is_default_base_url(str(base_url) if base_url else None),
50+
submit_to_llmobs=True,
5451
interface_type="chat_model",
5552
provider="anthropic",
5653
model=kwargs.get("model", ""),
@@ -118,14 +115,11 @@ async def traced_async_chat_model_generate(anthropic, pin, func, instance, args,
118115
chat_messages = get_argument_value(args, kwargs, 0, "messages")
119116
integration = anthropic._datadog_integration
120117
stream = False
121-
client = getattr(instance, "_client", None)
122-
base_url = getattr(client, "_base_url", None) if client else None
123118

124119
span = integration.trace(
125120
pin,
126121
"%s.%s" % (instance.__class__.__name__, func.__name__),
127-
# only report LLM Obs spans if base_url has not been changed
128-
submit_to_llmobs=integration.is_default_base_url(str(base_url) if base_url else None),
122+
submit_to_llmobs=True,
129123
interface_type="chat_model",
130124
provider="anthropic",
131125
model=kwargs.get("model", ""),

ddtrace/contrib/internal/botocore/services/bedrock.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -493,14 +493,7 @@ def patched_bedrock_api_call(original_func, instance, args, kwargs, function_var
493493
model_id = params.get("modelId")
494494
model_provider, model_name = _parse_model_id(model_id)
495495
integration = function_vars.get("integration")
496-
endpoint = getattr(instance, "_endpoint", None)
497-
endpoint_host = getattr(endpoint, "host", None) if endpoint else None
498-
# only report LLM Obs spans if base_url has not been changed
499-
submit_to_llmobs = (
500-
integration.llmobs_enabled
501-
and "embed" not in model_name
502-
and integration.is_default_base_url(str(endpoint_host) if endpoint_host else None)
503-
)
496+
submit_to_llmobs = integration.llmobs_enabled and "embed" not in model_name
504497
with core.context_with_data(
505498
"botocore.patched_bedrock_api_call",
506499
pin=pin,

ddtrace/contrib/internal/langchain/patch.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ def traced_llm_generate(langchain, pin, func, instance, args, kwargs):
171171
span = integration.trace(
172172
pin,
173173
"%s.%s" % (instance.__module__, instance.__class__.__name__),
174-
# only report LLM Obs spans if base_url has not been changed
175-
submit_to_llmobs=integration.has_default_base_url(instance),
174+
submit_to_llmobs=True,
176175
interface_type="llm",
177176
provider=llm_provider,
178177
model=model,
@@ -230,8 +229,7 @@ async def traced_llm_agenerate(langchain, pin, func, instance, args, kwargs):
230229
span = integration.trace(
231230
pin,
232231
"%s.%s" % (instance.__module__, instance.__class__.__name__),
233-
# only report LLM Obs spans if base_url has not been changed
234-
submit_to_llmobs=integration.has_default_base_url(instance),
232+
submit_to_llmobs=True,
235233
interface_type="llm",
236234
provider=llm_provider,
237235
model=model,
@@ -288,8 +286,7 @@ def traced_chat_model_generate(langchain, pin, func, instance, args, kwargs):
288286
span = integration.trace(
289287
pin,
290288
"%s.%s" % (instance.__module__, instance.__class__.__name__),
291-
# only report LLM Obs spans if base_url has not been changed
292-
submit_to_llmobs=integration.has_default_base_url(instance),
289+
submit_to_llmobs=True,
293290
interface_type="chat_model",
294291
provider=llm_provider,
295292
model=_extract_model_name(instance),
@@ -385,8 +382,7 @@ async def traced_chat_model_agenerate(langchain, pin, func, instance, args, kwar
385382
span = integration.trace(
386383
pin,
387384
"%s.%s" % (instance.__module__, instance.__class__.__name__),
388-
# only report LLM Obs spans if base_url has not been changed
389-
submit_to_llmobs=integration.has_default_base_url(instance),
385+
submit_to_llmobs=True,
390386
interface_type="chat_model",
391387
provider=llm_provider,
392388
model=_extract_model_name(instance),

ddtrace/contrib/internal/langchain/utils.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ def shared_stream(
8484
"pin": pin,
8585
"operation_id": f"{instance.__module__}.{instance.__class__.__name__}",
8686
"interface_type": interface_type,
87-
# submit to llmobs only if we detect an LLM request that is not being sent to a proxy
88-
"submit_to_llmobs": (
89-
integration.has_default_base_url(instance) if interface_type in ("chat_model", "llm") else True
90-
),
87+
"submit_to_llmobs": True,
9188
}
9289

9390
options.update(extra_options)

ddtrace/contrib/internal/openai/patch.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,7 @@ def patched_completions_with_raw_response_init(openai, pin, func, instance, args
206206

207207

208208
def _traced_endpoint(endpoint_hook, integration, instance, pin, args, kwargs):
209-
client = getattr(instance, "_client", None)
210-
base_url = getattr(client, "_base_url", None) if client else None
211-
212-
span = integration.trace(
213-
pin,
214-
endpoint_hook.OPERATION_ID,
215-
base_url=base_url,
216-
)
209+
span = integration.trace(pin, endpoint_hook.OPERATION_ID)
217210
openai_api_key = _format_openai_api_key(kwargs.get("api_key"))
218211
resp, err = None, None
219212
if openai_api_key:

ddtrace/llmobs/_integrations/anthropic.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from typing import List
66
from typing import Optional
77
from typing import Union
8-
from urllib.parse import urlparse
98

109
from ddtrace.internal.logger import get_logger
1110
from ddtrace.llmobs._constants import INPUT_MESSAGES
@@ -26,7 +25,6 @@
2625

2726
API_KEY = "anthropic.request.api_key"
2827
MODEL = "anthropic.request.model"
29-
DEFAULT_ANTHROPIC_HOSTNAME = "api.anthropic.com"
3028

3129

3230
class AnthropicIntegration(BaseLLMIntegration):
@@ -190,10 +188,3 @@ def record_usage(self, span: Span, usage: Dict[str, Any]) -> None:
190188
span.set_metric("anthropic.response.usage.output_tokens", output_tokens)
191189
if input_tokens is not None and output_tokens is not None:
192190
span.set_metric("anthropic.response.usage.total_tokens", input_tokens + output_tokens)
193-
194-
def is_default_base_url(self, base_url: Optional[str] = None) -> bool:
195-
if base_url is None:
196-
return True
197-
198-
parsed_url = urlparse(base_url)
199-
return parsed_url.hostname == DEFAULT_ANTHROPIC_HOSTNAME

ddtrace/llmobs/_integrations/bedrock.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import re
21
from typing import Any
32
from typing import Dict
43
from typing import List
54
from typing import Optional
65
from typing import Tuple
7-
from urllib.parse import urlparse
86

97
from ddtrace.internal.logger import get_logger
108
from ddtrace.llmobs._constants import INPUT_MESSAGES
@@ -22,8 +20,6 @@
2220

2321
log = get_logger(__name__)
2422

25-
BEDROCK_URL_REGEX_PATTERN = "^bedrock-runtime[\\w.-]*.com$"
26-
2723

2824
class BedrockIntegration(BaseLLMIntegration):
2925
_integration_name = "bedrock"
@@ -271,11 +267,3 @@ def _extract_output_message(response):
271267
return [{"content": str(content)} for content in response["text"]]
272268
if isinstance(response["text"][0], dict):
273269
return [{"content": response["text"][0].get("text", "")}]
274-
275-
def is_default_base_url(self, base_url: Optional[str] = None) -> bool:
276-
if base_url is None:
277-
return True
278-
279-
parsed_url = urlparse(base_url)
280-
default_url_regex = re.compile(BEDROCK_URL_REGEX_PATTERN)
281-
return default_url_regex.match(parsed_url.hostname or "") is not None

ddtrace/llmobs/_integrations/langchain.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
from ddtrace.llmobs._constants import TOTAL_TOKENS_METRIC_KEY
3131
from ddtrace.llmobs._integrations.base import BaseLLMIntegration
3232
from ddtrace.llmobs._integrations.utils import format_langchain_io
33-
from ddtrace.llmobs._integrations.utils import is_openai_default_base_url
3433
from ddtrace.llmobs._utils import _get_nearest_llmobs_ancestor
3534
from ddtrace.llmobs.utils import Document
3635
from ddtrace.trace import Span
@@ -726,7 +725,3 @@ def check_token_usage_ai_message(self, ai_message):
726725
total_tokens = usage.get("total_tokens", input_tokens + output_tokens)
727726

728727
return (input_tokens, output_tokens, total_tokens), run_id_base
729-
730-
def has_default_base_url(self, instance) -> bool:
731-
openai_api_base = getattr(instance, "openai_api_base", None)
732-
return not openai_api_base or is_openai_default_base_url(openai_api_base)

ddtrace/llmobs/_integrations/openai.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from ddtrace.llmobs._constants import TOTAL_TOKENS_METRIC_KEY
1919
from ddtrace.llmobs._integrations.base import BaseLLMIntegration
2020
from ddtrace.llmobs._integrations.utils import get_llmobs_metrics_tags
21-
from ddtrace.llmobs._integrations.utils import is_openai_default_base_url
2221
from ddtrace.llmobs._integrations.utils import openai_set_meta_tags_from_chat
2322
from ddtrace.llmobs._integrations.utils import openai_set_meta_tags_from_completion
2423
from ddtrace.llmobs._utils import _get_attr
@@ -53,10 +52,8 @@ def user_api_key(self, value: str) -> None:
5352
self._user_api_key = "sk-...%s" % value[-4:]
5453

5554
def trace(self, pin: Pin, operation_id: str, submit_to_llmobs: bool = False, **kwargs: Dict[str, Any]) -> Span:
56-
base_url = kwargs.get("base_url", None)
57-
submit_to_llmobs = self.is_default_base_url(str(base_url) if base_url else None) and (
58-
operation_id.endswith("Completion") or operation_id == "createEmbedding"
59-
)
55+
if operation_id.endswith("Completion") or operation_id == "createEmbedding":
56+
submit_to_llmobs = True
6057
return super().trace(pin, operation_id, submit_to_llmobs, **kwargs)
6158

6259
def _set_base_span_tags(self, span: Span, **kwargs) -> None:
@@ -171,6 +168,3 @@ def _extract_llmobs_metrics_tags(span: Span, resp: Any) -> Dict[str, Any]:
171168
TOTAL_TOKENS_METRIC_KEY: prompt_tokens + completion_tokens,
172169
}
173170
return get_llmobs_metrics_tags("openai", span)
174-
175-
def is_default_base_url(self, base_url: Optional[str] = None) -> bool:
176-
return is_openai_default_base_url(base_url)

ddtrace/llmobs/_integrations/utils.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
from dataclasses import dataclass
33
from dataclasses import is_dataclass
44
import json
5-
import re
65
from typing import Any
76
from typing import Dict
87
from typing import List
98
from typing import Optional
109
from typing import Tuple
1110
from typing import Union
12-
from urllib.parse import urlparse
1311

1412
from ddtrace._trace.span import Span
1513
from ddtrace.internal import core
@@ -31,8 +29,6 @@
3129

3230
logger = get_logger(__name__)
3331

34-
ACCEPTED_OPENAI_DEFAULT_HOSTNAMES = ("api.openai.com", "api.deepseek.com")
35-
AZURE_URL_REGEX_PATTERN = "^[\\w.-]*openai\\.azure\\.com$"
3632
OPENAI_SKIPPED_COMPLETION_TAGS = (
3733
"model",
3834
"prompt",
@@ -53,16 +49,6 @@
5349
)
5450

5551

56-
def is_openai_default_base_url(base_url: Optional[str] = None) -> bool:
57-
if base_url is None:
58-
return True
59-
60-
parsed_url = urlparse(base_url)
61-
default_azure_endpoint_regex = re.compile(AZURE_URL_REGEX_PATTERN)
62-
matches_azure_endpoint = default_azure_endpoint_regex.match(parsed_url.hostname or "") is not None
63-
return parsed_url.hostname in ACCEPTED_OPENAI_DEFAULT_HOSTNAMES or matches_azure_endpoint
64-
65-
6652
def extract_model_name_google(instance, model_name_attr):
6753
"""Extract the model name from the instance.
6854
Model names are stored in the format `"models/{model_name}"`

0 commit comments

Comments
 (0)