Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(langchain): handle secret str api keys [backport 2.1] #7480

Merged
merged 2 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions ddtrace/contrib/langchain/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import langchain
from langchain.callbacks.openai_info import get_openai_token_cost_for_model
from pydantic import SecretStr

from ddtrace import config
from ddtrace.constants import ERROR_TYPE
Expand Down Expand Up @@ -140,8 +141,11 @@ def _extract_model_name(instance):


def _format_api_key(api_key):
# type: (str) -> str
# type: (str | SecretStr) -> str
"""Obfuscate a given LLM provider API key by returning the last four characters."""
if hasattr(api_key, "get_secret_value"):
api_key = api_key.get_secret_value()

if not api_key or len(api_key) < 4:
return ""
return "...%s" % api_key[-4:]
Expand Down Expand Up @@ -695,7 +699,7 @@ def traced_similarity_search(langchain, pin, func, instance, args, kwargs):
instance._index.configuration.server_variables.get("project_name", ""),
)
api_key = instance._index.configuration.api_key.get("ApiKeyAuth", "")
span.set_tag_str(API_KEY, "...%s" % api_key[-4:]) # override api_key for Pinecone
span.set_tag_str(API_KEY, _format_api_key(api_key)) # override api_key for Pinecone
documents = func(*args, **kwargs)
span.set_metric("langchain.response.document_count", len(documents))
for idx, document in enumerate(documents):
Expand Down
1 change: 1 addition & 0 deletions docs/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ proxying
psutil
psycopg
py
pydantic
pyenv
PyFrameObject
pylibmc
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fixes:
- |
langchain: This fix resolves an issue with tagging pydantic `SecretStr` type api keys.
23 changes: 8 additions & 15 deletions tests/contrib/langchain/test_langchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ def langchain(ddtrace_config_langchain, mock_logs, mock_metrics):
with override_config("langchain", ddtrace_config_langchain):
# ensure that mock OpenAI API key is passed in
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "<not-a-real-key>")
os.environ["COHERE_API_KEY"] = os.getenv("COHERE_API_KEY", "<not-a-real-key>")
os.environ["HUGGINGFACEHUB_API_TOKEN"] = os.getenv("HUGGINGFACEHUB_API_TOKEN", "<not-a-real-key>")
os.environ["AI21_API_KEY"] = os.getenv("AI21_API_KEY", "<not-a-real-key>")
patch()
import langchain

Expand Down Expand Up @@ -1078,9 +1081,7 @@ def test_pinecone_vectorstore_similarity_search(langchain, request_vcr):
api_key=os.getenv("PINECONE_API_KEY", "<not-a-real-key>"),
environment=os.getenv("PINECONE_ENV", "<not-a-real-env>"),
)
embed = langchain.embeddings.OpenAIEmbeddings(
model="text-embedding-ada-002", openai_api_key=os.getenv("OPENAI_API_KEY", "<not-a-real-key>")
)
embed = langchain.embeddings.OpenAIEmbeddings(model="text-embedding-ada-002")
index = pinecone.Index(index_name="langchain-retrieval")
vectorstore = langchain.vectorstores.Pinecone(index, embed.embed_query, "text")
vectorstore.similarity_search("Who was Alan Turing?", 1)
Expand All @@ -1100,9 +1101,7 @@ def test_pinecone_vectorstore_retrieval_chain(langchain, request_vcr):
api_key=os.getenv("PINECONE_API_KEY", "<not-a-real-key>"),
environment=os.getenv("PINECONE_ENV", "<not-a-real-env>"),
)
embed = langchain.embeddings.OpenAIEmbeddings(
model="text-embedding-ada-002", openai_api_key=os.getenv("OPENAI_API_KEY", "<not-a-real-key>")
)
embed = langchain.embeddings.OpenAIEmbeddings(model="text-embedding-ada-002")
index = pinecone.Index(index_name="langchain-retrieval")
vectorstore = langchain.vectorstores.Pinecone(index, embed.embed_query, "text")

Expand All @@ -1127,9 +1126,7 @@ def test_pinecone_vectorstore_retrieval_chain_39(langchain, request_vcr):
api_key=os.getenv("PINECONE_API_KEY", "<not-a-real-key>"),
environment=os.getenv("PINECONE_ENV", "<not-a-real-env>"),
)
embed = langchain.embeddings.OpenAIEmbeddings(
model="text-embedding-ada-002", openai_api_key=os.getenv("OPENAI_API_KEY", "<not-a-real-key>")
)
embed = langchain.embeddings.OpenAIEmbeddings(model="text-embedding-ada-002")
index = pinecone.Index(index_name="langchain-retrieval")
vectorstore = langchain.vectorstores.Pinecone(index, embed.embed_query, "text")

Expand All @@ -1152,9 +1149,7 @@ def test_vectorstore_similarity_search_metrics(langchain, request_vcr, mock_metr
api_key=os.getenv("PINECONE_API_KEY", "<not-a-real-key>"),
environment=os.getenv("PINECONE_ENV", "<not-a-real-env>"),
)
embed = langchain.embeddings.OpenAIEmbeddings(
model="text-embedding-ada-002", openai_api_key=os.getenv("OPENAI_API_KEY", "<not-a-real-key>")
)
embed = langchain.embeddings.OpenAIEmbeddings(model="text-embedding-ada-002")
index = pinecone.Index(index_name="langchain-retrieval")
vectorstore = langchain.vectorstores.Pinecone(index, embed.embed_query, "text")
vectorstore.similarity_search("Who was Alan Turing?", 1)
Expand Down Expand Up @@ -1205,9 +1200,7 @@ def test_vectorstore_logs(langchain, ddtrace_config_langchain, request_vcr, mock
api_key=os.getenv("PINECONE_API_KEY", "<not-a-real-key>"),
environment=os.getenv("PINECONE_ENV", "<not-a-real-env>"),
)
embed = langchain.embeddings.OpenAIEmbeddings(
model="text-embedding-ada-002", openai_api_key=os.getenv("OPENAI_API_KEY", "<not-a-real-key>")
)
embed = langchain.embeddings.OpenAIEmbeddings(model="text-embedding-ada-002")
index = pinecone.Index(index_name="langchain-retrieval")
vectorstore = langchain.vectorstores.Pinecone(index, embed.embed_query, "text")
vectorstore.similarity_search("Who was Alan Turing?", 1)
Expand Down