Skip to content

Commit

Permalink
Expose playground type in add_routes and APIHandler (#519)
Browse files Browse the repository at this point in the history
This PR adds a playground_type parameter to add_routes and APIHandler that creates a new playground that's specialized for chat applications

Co-authored-by: jacoblee93 <jacoblee93@gmail.com>
  • Loading branch information
eyurtsev and jacoblee93 committed Mar 11, 2024
1 parent 3fa47b2 commit f0171fa
Show file tree
Hide file tree
Showing 10 changed files with 33 additions and 140 deletions.
1 change: 1 addition & 0 deletions examples/chat_playground/server.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class InputChat(BaseModel):
chain.with_types(input_type=InputChat),
enable_feedback_endpoint=True,
enable_public_trace_link_endpoint=True,
playground_type="chat",
)

if __name__ == "__main__":
Expand Down
4 changes: 3 additions & 1 deletion langserve/api_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
from starlette.responses import JSONResponse, Response

from langserve.callbacks import AsyncEventAggregatorCallback, CallbackEventDict
from langserve.chat_playground import serve_chat_playground
from langserve.lzstring import LZString
from langserve.playground import serve_playground
from langserve.pydantic_v1 import BaseModel, Field, ValidationError, create_model
Expand Down Expand Up @@ -468,6 +467,7 @@ def __init__(
enable_public_trace_link_endpoint: bool = False,
per_req_config_modifier: Optional[PerRequestConfigModifier] = None,
stream_log_name_allow_list: Optional[Sequence[str]] = None,
playground_type: Literal["default", "chat"] = "default",
) -> None:
"""Create an API handler for the given runnable.
Expand Down Expand Up @@ -620,6 +620,7 @@ def __init__(
model_namespace, output_type_
)
self._BatchResponse = create_batch_response_model(model_namespace, output_type_)
self.playground_type = playground_type

@property
def InvokeRequest(self) -> Type[BaseModel]:
Expand Down Expand Up @@ -1365,6 +1366,7 @@ async def playground(
file_path,
feedback_enabled,
public_trace_link_enabled,
playground_type=self.playground_type,
)

async def chat_playground(
Expand Down
98 changes: 0 additions & 98 deletions langserve/chat_playground.py

This file was deleted.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion langserve/chat_playground/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<link rel="icon" href="/____LANGSERVE_BASE_URL/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Chat Playground</title>
<script type="module" crossorigin src="/____LANGSERVE_BASE_URL/assets/index-34f4a840.js"></script>
<script type="module" crossorigin src="/____LANGSERVE_BASE_URL/assets/index-9018861a.js"></script>
<link rel="stylesheet" href="/____LANGSERVE_BASE_URL/assets/index-b47ed17e.css">
</head>
<body>
Expand Down
4 changes: 2 additions & 2 deletions langserve/chat_playground/src/components/ShareDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export function ShareDialog(props: { config: unknown; children: ReactNode }) {
// get base URL
const targetUrl = `${state.basePath}/c/${hash}`;

// .../c/[hash]/chat_playground
const playgroundUrl = `${targetUrl}/chat_playground`;
// .../c/[hash]/playground
const playgroundUrl = `${targetUrl}/playground`;

// cURL, JS: .../c/[hash]/invoke
// Python: .../c/[hash]
Expand Down
4 changes: 2 additions & 2 deletions langserve/chat_playground/src/utils/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export function getStateFromUrl(path: string) {
basePath = basePath.slice(0, -1);
}

if (basePath.endsWith("/chat_playground")) {
basePath = basePath.slice(0, -"/chat_playground".length);
if (basePath.endsWith("/playground")) {
basePath = basePath.slice(0, -"/playground".length);
}

// check if we can omit the last segment
Expand Down
19 changes: 13 additions & 6 deletions langserve/playground.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import mimetypes
import os
from string import Template
from typing import Sequence, Type
from typing import Literal, Sequence, Type

from fastapi.responses import Response
from langchain.schema.runnable import Runnable
Expand Down Expand Up @@ -55,23 +55,30 @@ async def serve_playground(
file_path: str,
feedback_enabled: bool,
public_trace_link_enabled: bool,
playground_type: Literal["default", "chat"],
) -> Response:
"""Serve the playground."""
if playground_type == "default":
path_to_dist = "./playground/dist"
elif playground_type == "chat":
path_to_dist = "./chat_playground/dist"
else:
raise ValueError(
f"Invalid playground type: {playground_type}. Use one of 'default' or 'chat'."
)

local_file_path = os.path.abspath(
os.path.join(
os.path.dirname(__file__),
"./playground/dist",
path_to_dist,
file_path or "index.html",
)
)

base_dir = os.path.abspath(
os.path.join(os.path.dirname(__file__), "./playground/dist")
)
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), path_to_dist))

if base_dir != os.path.commonpath((base_dir, local_file_path)):
return Response("Not Found", status_code=404)

try:
with open(local_file_path, encoding="utf-8") as f:
mime_type = _get_mimetype(local_file_path)
Expand Down
31 changes: 6 additions & 25 deletions langserve/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ def _register_path_for_app(app: Union[FastAPI, APIRouter], path: str) -> None:
"stream_log",
"stream_events",
"playground",
"chat_playground",
"feedback",
"public_trace_link",
"input_schema",
Expand All @@ -130,7 +129,6 @@ def _register_path_for_app(app: Union[FastAPI, APIRouter], path: str) -> None:
"stream_log",
"stream_events",
"playground",
"chat_playground",
"feedback",
"public_trace_link",
"input_schema",
Expand Down Expand Up @@ -179,7 +177,6 @@ def __init__(
is_stream_log_enabled = True
is_stream_events_enabled = True
is_playground_enabled = True
is_chat_playground_enabled = True
is_input_schema_enabled = True
is_output_schema_enabled = True
is_config_schema_enabled = True
Expand All @@ -197,9 +194,6 @@ def __init__(
is_stream_log_enabled = "stream_log" not in disabled_endpoints_
is_stream_events_enabled = "stream_events" not in disabled_endpoints_
is_playground_enabled = "playground" not in disabled_endpoints_
is_chat_playground_enabled = (
"chat_playground" not in disabled_endpoints_
)
is_input_schema_enabled = "input_schema" not in disabled_endpoints_
is_output_schema_enabled = "output_schema" not in disabled_endpoints_
is_config_schema_enabled = "config_schema" not in disabled_endpoints_
Expand All @@ -216,7 +210,6 @@ def __init__(
is_stream_log_enabled = "stream_log" in enabled_endpoints_
is_stream_events_enabled = "stream_events" in enabled_endpoints_
is_playground_enabled = "playground" in enabled_endpoints_
is_chat_playground_enabled = "chat_playground" in enabled_endpoints_
is_input_schema_enabled = "input_schema" in enabled_endpoints_
is_output_schema_enabled = "output_schema" in enabled_endpoints_
is_config_schema_enabled = "config_schema" in enabled_endpoints_
Expand All @@ -228,7 +221,6 @@ def __init__(
self.is_stream_log_enabled = is_stream_log_enabled
self.is_stream_events_enabled = is_stream_events_enabled
self.is_playground_enabled = is_playground_enabled
self.is_chat_playground_enabled = is_chat_playground_enabled
self.is_input_schema_enabled = is_input_schema_enabled
self.is_output_schema_enabled = is_output_schema_enabled
self.is_config_schema_enabled = is_config_schema_enabled
Expand Down Expand Up @@ -256,6 +248,7 @@ def add_routes(
stream_log_name_allow_list: Optional[Sequence[str]] = None,
enabled_endpoints: Optional[Sequence[EndpointName]] = None,
dependencies: Optional[Sequence[Depends]] = None,
playground_type: Literal["default", "chat"] = "default",
) -> None:
"""Register the routes on the given FastAPI app or APIRouter.
Expand Down Expand Up @@ -307,13 +300,13 @@ def add_routes(
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.
A PUBLICLY 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*,
*playground*, *chat_playground*, *input_schema*, *output_schema*,
*playground*, *input_schema*, *output_schema*,
*config_schema*, *config_hashes*.
*config_hashes* represents the config hash variant (when it exists)
Expand All @@ -337,7 +330,7 @@ def add_routes(
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*,
*playground*, *chat_playground*, *input_schema*, *output_schema*,
*playground*, *input_schema*, *output_schema*,
*config_schema*, *config_hashes*.
*config_hashes* represents the config hash variant (when it exists)
Expand All @@ -358,6 +351,7 @@ def add_routes(
stream as intermediate steps
dependencies: list of dependencies to be applied to the *path operation*.
See [FastAPI docs for Dependencies in path operation decorators](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/).
playground_type: The type of playground to serve. The default is "default".
""" # noqa: E501
endpoint_configuration = _EndpointConfiguration(
enabled_endpoints=enabled_endpoints,
Expand Down Expand Up @@ -410,6 +404,7 @@ def add_routes(
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,
playground_type=playground_type,
)
namespace = path or ""

Expand Down Expand Up @@ -702,20 +697,6 @@ async def config_schema_with_config(
include_in_schema=False,
)(playground)

if endpoint_configuration.is_chat_playground_enabled:
chat_playground = app.get(
namespace + "/chat_playground/{file_path:path}",
dependencies=dependencies,
include_in_schema=False,
)(api_handler.chat_playground)

if endpoint_configuration.is_config_hash_enabled:
app.get(
namespace + "/c/{config_hash}/chat_playground/{file_path:path}",
dependencies=dependencies,
include_in_schema=False,
)(chat_playground)

if enable_feedback_endpoint:
app.post(
namespace + "/feedback",
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ readme = "README.md"
authors = ["LangChain"]
license = "LangServe"
repository = "https://github.com/langchain-ai/langserve"
exclude = ["langserve/playground"]
include = ["langserve/playground/dist/**/*"]
exclude = ["langserve/playground,langserve/chat_playground"]
include = ["langserve/playground/dist/**/*", "langserve/chat_playground/dist/**/*"]

[tool.poetry.dependencies]
python = "^3.8.1"
Expand Down

0 comments on commit f0171fa

Please sign in to comment.