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

Adds opt-in public trace view endpoint #511

Merged
merged 3 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
56 changes: 54 additions & 2 deletions langserve/api_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
CustomUserType,
Feedback,
FeedbackCreateRequest,
PublicTraceLink,
PublicTraceLinkCreateRequest,
SingletonResponseMetadata,
)
from langserve.serialization import WellKnownLCSerializer
Expand Down Expand Up @@ -462,6 +464,7 @@ def __init__(
config_keys: Sequence[str] = ("configurable",),
include_callback_events: bool = False,
enable_feedback_endpoint: bool = False,
enable_public_trace_link_endpoint: bool = False,
per_req_config_modifier: Optional[PerRequestConfigModifier] = None,
stream_log_name_allow_list: Optional[Sequence[str]] = None,
) -> None:
Expand Down Expand Up @@ -502,6 +505,13 @@ def __init__(
to LangSmith. Disabled by default. If this flag is disabled or LangSmith
tracing is not enabled for the runnable, then 4xx errors will be thrown
when accessing the feedback endpoint
enable_public_trace_link_endpoint: Whether to enable an endpoint for
end-users to publicly view LangSmith traces of your chain runs.
WARNING: THIS WILL EXPOSE THE INTERNAL STATE OF YOUR RUN AND CHAIN AS
A PUBLICY ACCESSIBLE LINK.
If this flag is disabled or LangSmith tracing is not enabled for
the runnable, then 400 errors will be thrown when accessing the
endpoint.
per_req_config_modifier: optional function that can be used to update the
RunnableConfig for a given run based on the raw request. This is useful,
for example, if the user wants to pass in a header containing
Expand Down Expand Up @@ -548,6 +558,7 @@ def __init__(
self._per_req_config_modifier = per_req_config_modifier
self._serializer = WellKnownLCSerializer()
self._enable_feedback_endpoint = enable_feedback_endpoint
self._enable_public_trace_link_endpoint = enable_public_trace_link_endpoint
self._names_in_stream_allow_list = stream_log_name_allow_list

# Client is patched using mock.patch, if changing the names
Expand Down Expand Up @@ -1366,7 +1377,7 @@ async def create_feedback(
raise HTTPException(
400,
"The feedback endpoint is only accessible when LangSmith is "
+ "enabled on your LangServe server."
+ "enabled on your LangServe server.\n"
+ "Please set `enable_feedback_endpoint=True` on your route and "
+ "set the proper environment variables",
)
Expand Down Expand Up @@ -1406,11 +1417,52 @@ async def _check_feedback_enabled(self) -> None:
raise HTTPException(
400,
"The feedback endpoint is only accessible when LangSmith is "
+ "enabled on your LangServe server."
+ "enabled on your LangServe server.\n"
+ "Please set `enable_feedback_endpoint=True` on your route and "
+ "set the proper environment variables",
)

async def check_feedback_enabled(self) -> bool:
"""Check if feedback is enabled for the runnable."""
return self._enable_feedback_endpoint or not tracing_is_enabled()

async def create_public_trace_link(
self, public_trace_link_create_req: PublicTraceLinkCreateRequest
) -> PublicTraceLink:
"""Send feedback on an individual run to langsmith

Note that a successful response means that feedback was successfully
submitted. It does not guarantee that the feedback is recorded by
langsmith. Requests may be silently rejected if they are
unauthenticated or invalid by the server.
"""
if not tracing_is_enabled() or not self._enable_public_trace_link_endpoint:
raise HTTPException(
400,
"The public trace link endpoint is only accessible when "
+ "LangSmith is enabled on your LangServe server.\n"
+ "Please set `enable_public_trace_link_endpoint=True` on your "
+ "route and set the proper environment variables",
)
public_url = self._langsmith_client.share_run(
public_trace_link_create_req.run_id,
)
return PublicTraceLink(public_url=public_url)

async def _check_public_trace_link_enabled(self) -> None:
jacoblee93 marked this conversation as resolved.
Show resolved Hide resolved
"""Check if public trace links are enabled for the runnable.

This endpoint is private since it will be deprecated in the future.
"""
if not (await self.check_public_trace_link_enabled()):
raise HTTPException(
400,
"The public trace link endpoint is only accessible when "
+ "LangSmith is enabled on your LangServe server.\n"
+ "Please set `enable_public_trace_link_endpoint=True` on your "
+ "route and set the proper environment variables",
)

async def check_public_trace_link_enabled(self) -> bool:
"""Check if public trace links are enabled for the runnable."""
return self._enable_public_trace_link_endpoint or not tracing_is_enabled()
4 changes: 4 additions & 0 deletions langserve/playground.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ async def serve_playground(
base_url: str,
file_path: str,
feedback_enabled: bool,
public_trace_link_enabled: bool,
) -> Response:
"""Serve the playground."""
local_file_path = os.path.abspath(
Expand Down Expand Up @@ -86,6 +87,9 @@ async def serve_playground(
LANGSERVE_FEEDBACK_ENABLED=json.dumps(
"true" if feedback_enabled else "false"
),
LANGSERVE_PUBLIC_TRACE_LINK_ENABLED=json.dumps(
"true" if public_trace_link_enabled else "false"
),
)
else:
response = f.buffer.read()
Expand Down
1 change: 1 addition & 0 deletions langserve/playground/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
window.CONFIG_SCHEMA = ____LANGSERVE_CONFIG_SCHEMA;
window.INPUT_SCHEMA = ____LANGSERVE_INPUT_SCHEMA;
window.FEEDBACK_ENABLED = ____LANGSERVE_FEEDBACK_ENABLED;
window.PUBLIC_TRACE_LINK_ENABLED = ____LANGSERVE_PUBLIC_TRACE_LINK_ENABLED;
} catch (error) {
// pass
}
Expand Down
1 change: 1 addition & 0 deletions langserve/playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
window.CONFIG_SCHEMA = ____LANGSERVE_CONFIG_SCHEMA;
window.INPUT_SCHEMA = ____LANGSERVE_INPUT_SCHEMA;
window.FEEDBACK_ENABLED = ____LANGSERVE_FEEDBACK_ENABLED;
window.PUBLIC_TRACE_LINK_ENABLED = ____LANGSERVE_PUBLIC_TRACE_LINK_ENABLED;
} catch (error) {
// pass
}
Expand Down
18 changes: 18 additions & 0 deletions langserve/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,21 @@ class Feedback(BaseFeedback):

correction: Optional[Dict] = None
"""Correction for the run."""


class PublicTraceLinkCreateRequest(BaseModel):
"""
Represents a request that creates a public trace for an individual run
"""

run_id: UUID
"""The unique ID of the run to share."""


class PublicTraceLink(BaseModel):
"""
Represents a public trace for an individual run
"""

public_url: str
"""Public URL for the trace."""
31 changes: 28 additions & 3 deletions langserve/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def _register_path_for_app(app: Union[FastAPI, APIRouter], path: str) -> None:
"stream_events",
"playground",
"feedback",
"public_trace_link",
"input_schema",
"config_schema",
"output_schema",
Expand All @@ -129,6 +130,7 @@ def _register_path_for_app(app: Union[FastAPI, APIRouter], path: str) -> None:
"stream_events",
"playground",
"feedback",
"public_trace_link",
"input_schema",
"config_schema",
"output_schema",
Expand All @@ -145,6 +147,7 @@ def __init__(
enabled_endpoints: Optional[Sequence[EndpointName]] = None,
disabled_endpoints: Optional[Sequence[EndpointName]] = None,
enable_feedback_endpoint: bool = False,
enable_public_trace_link_endpoint: bool = False,
) -> None:
"""Initialize the endpoint configuration."""
if enabled_endpoints and disabled_endpoints:
Expand Down Expand Up @@ -223,6 +226,7 @@ def __init__(
self.is_config_schema_enabled = is_config_schema_enabled
self.is_config_hash_enabled = is_config_hash_enabled
self.is_feedback_enabled = enable_feedback_endpoint
self.is_public_trace_link_enabled = enable_public_trace_link_endpoint


# PUBLIC API
Expand All @@ -239,6 +243,7 @@ def add_routes(
include_callback_events: bool = False,
per_req_config_modifier: Optional[PerRequestConfigModifier] = None,
enable_feedback_endpoint: bool = _is_hosted(),
enable_public_trace_link_endpoint: bool = False,
disabled_endpoints: Optional[Sequence[EndpointName]] = None,
stream_log_name_allow_list: Optional[Sequence[str]] = None,
enabled_endpoints: Optional[Sequence[EndpointName]] = None,
Expand Down Expand Up @@ -290,7 +295,13 @@ def add_routes(
enable_feedback_endpoint: Whether to enable an endpoint for logging feedback
to LangSmith. Enabled by default. If this flag is disabled or LangSmith
tracing is not enabled for the runnable, then 400 errors will be thrown
when accessing the feedback endpoint
when accessing the feedback endpoint.
enable_public_trace_link_endpoint: Whether to enable an endpoint for
end-users to publicly view LangSmith traces of your chain runs.
WARNING: THIS WILL EXPOSE THE INTERNAL STATE OF YOUR RUN AND CHAIN AS
A PUBLICY ACCESSIBLE LINK.
If this flag is disabled or LangSmith tracing is not enabled for
the runnable, then 400 errors will be thrown when accessing the endpoint.
enabled_endpoints: A list of endpoints which should be enabled. If not
specified, all associated endpoints will be enabled. The list can contain
the following values: *invoke*, *batch*, *stream*, *stream_log*,
Expand All @@ -312,8 +323,9 @@ def add_routes(
)
```

Please note that the feedback endpoint is not included in this list
and is controlled by the `enable_feedback_endpoint` flag.
Please note that the feedback endpoint and public trace link endpoints
are not included in this list and are controlled by their
respective flags.
disabled_endpoints: A list of endpoints which should be disabled. If not
specified, all associated endpoints will be enabled. The list can contain
the following values: *invoke*, *batch*, *stream*, *stream_log*,
Expand Down Expand Up @@ -343,6 +355,7 @@ def add_routes(
enabled_endpoints=enabled_endpoints,
disabled_endpoints=disabled_endpoints,
enable_feedback_endpoint=enable_feedback_endpoint,
enable_public_trace_link_endpoint=enable_public_trace_link_endpoint,
)

try:
Expand Down Expand Up @@ -386,6 +399,7 @@ def add_routes(
config_keys=config_keys,
include_callback_events=include_callback_events,
enable_feedback_endpoint=enable_feedback_endpoint,
enable_public_trace_link_endpoint=enable_public_trace_link_endpoint,
per_req_config_modifier=per_req_config_modifier,
stream_log_name_allow_list=stream_log_name_allow_list,
)
Expand Down Expand Up @@ -691,6 +705,17 @@ async def config_schema_with_config(
dependencies=dependencies,
)(api_handler._check_feedback_enabled)

if enable_public_trace_link_endpoint:
app.put(
namespace + "/public_trace_link",
dependencies=dependencies,
)(api_handler.create_public_trace_link)

app.head(
namespace + "/public_trace_link",
dependencies=dependencies,
)(api_handler._check_public_trace_link_enabled)
jacoblee93 marked this conversation as resolved.
Show resolved Hide resolved

#######################################
# Documentation variants of end points.
#######################################
Expand Down
Loading