Skip to content

Commit

Permalink
Merge branch 'main' into dqbd/feedback-playground
Browse files Browse the repository at this point in the history
  • Loading branch information
dqbd committed Nov 27, 2023
2 parents 8dc4d15 + af904f5 commit ab00b6c
Show file tree
Hide file tree
Showing 36 changed files with 1,890 additions and 1,130 deletions.
2 changes: 1 addition & 1 deletion .clabot
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"contributors": ["eyurtsev", "hwchase17", "nfcampos", "efriis", "jacoblee93", "dqbd", "kreneskyp", "adarsh-jha-dev", "harris", "baskaryan", "hinthornw", "bracesproul", "jakerachleff"],
"contributors": ["eyurtsev", "hwchase17", "nfcampos", "efriis", "jacoblee93", "dqbd", "kreneskyp", "adarsh-jha-dev", "harris", "baskaryan", "hinthornw", "bracesproul", "jakerachleff", "craigsdennis", "anhi"],
"message": "Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have the username {{usersWithoutCLA}} on file. In order for us to review and merge your code, please complete the Individual Contributor License Agreement here https://forms.gle/Ljhqvt9Gdi1N385W6 .\n\nThis process is done manually on our side, so after signing the form one of the maintainers will add you to the contributors list.\n\nFor more details about why we have a CLA and other contribution guidelines please see: https://github.com/langchain-ai/langserve/blob/main/CONTRIBUTING.md."
}
1 change: 1 addition & 0 deletions .github/workflows/langserve_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- '.github/workflows/_test.yml'
- '.github/workflows/langserve_ci.yml'
- 'langserve/**'
- 'tests/**'
- 'examples/**'
- 'pyproject.toml'
- 'poetry.lock'
Expand Down
71 changes: 47 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ We will be releasing a hosted version of LangServe for one-click deployments of
## Security

* Vulnerability in Versions 0.0.13 - 0.0.15 -- playground endpoint allows accessing arbitrary files on server. [Resolved in 0.0.16](https://github.com/langchain-ai/langserve/pull/98).

## Installation

For both client and server:

```bash
pip install "langserve[all]"
```

or `pip install "langserve[client]"` for client code, and `pip install "langserve[server]"` for server code.


## LangChain CLI 🛠️

Expand Down Expand Up @@ -97,7 +108,7 @@ prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
add_routes(
app,
prompt | model,
path="/chain",
path="/joke",
)

if __name__ == "__main__":
Expand All @@ -110,17 +121,16 @@ if __name__ == "__main__":

If you've deployed the server above, you can view the generated OpenAPI docs using:

> ⚠️ If using pydantic v2, docs will not be generated for invoke/batch/stream/stream_log. See [Pydantic](#pydantic) section below for more details.
```sh
curl localhost:8000/docs
```

make sure to **add** the `/docs` suffix.

Below will return a 404 until you define a `@app.get("/")`

```sh
localhost:8000
```
> ⚠️ Index page `/` is not defined by **design**, so `curl localhost:8000` or visiting the URL
> will return a 404. If you want content at `/` define an endpoint `@app.get("/")`.
### Client

Expand All @@ -135,7 +145,7 @@ from langserve import RemoteRunnable

openai = RemoteRunnable("http://localhost:8000/openai/")
anthropic = RemoteRunnable("http://localhost:8000/anthropic/")
joke_chain = RemoteRunnable("http://localhost:8000/chain/")
joke_chain = RemoteRunnable("http://localhost:8000/joke/")

joke_chain.invoke({"topic": "parrots"})

Expand Down Expand Up @@ -170,7 +180,7 @@ In TypeScript (requires LangChain.js version 0.0.166 or later):
import { RemoteRunnable } from "langchain/runnables/remote";

const chain = new RemoteRunnable({
url: `http://localhost:8000/chain/invoke/`,
url: `http://localhost:8000/joke/`,
});
const result = await chain.invoke({
topic: "cats",
Expand All @@ -182,7 +192,7 @@ Python using `requests`:
```python
import requests
response = requests.post(
"http://localhost:8000/chain/invoke/",
"http://localhost:8000/joke/invoke/",
json={'input': {'topic': 'cats'}}
)
response.json()
Expand All @@ -191,7 +201,7 @@ response.json()
You can also use `curl`:

```sh
curl --location --request POST 'http://localhost:8000/chain/invoke/' \
curl --location --request POST 'http://localhost:8000/joke/invoke/' \
--header 'Content-Type: application/json' \
--data-raw '{
"input": {
Expand Down Expand Up @@ -223,21 +233,27 @@ adds of these endpoints to the server:
- `GET /my_runnable/output_schema` - json schema for output of the runnable
- `GET /my_runnable/config_schema` - json schema for config of the runnable

These endpoints match the [LangChain Expression Language interface](https://python.langchain.com/docs/expression_language/interface) -- please reference this documentation for more details.

## Playground

You can find a playground page for your runnable at `/my_runnable/playground`. This exposes a simple UI to [configure](https://python.langchain.com/docs/expression_language/how_to/configure) and invoke your runnable with streaming output and intermediate steps.

![image](https://github.com/langchain-ai/langserve/assets/3205522/5ca56e29-f1bb-40f4-84b5-15916384a276)
<p align="center">
<img src="https://github.com/langchain-ai/langserve/assets/3205522/5ca56e29-f1bb-40f4-84b5-15916384a276" width="50%"/>
</p>

## Installation
### Widgets

For both client and server:
The playground supports [widgets](#playground-widgets) and can be used to test your runnable with different inputs.

```bash
pip install "langserve[all]"
```
In addition, for configurable runnables, the playground will allow you to configure the runnable and share a link with the configuration:

or `pip install "langserve[client]"` for client code, and `pip install "langserve[server]"` for server code.
### Sharing

<p align="center">
<img src="https://github.com/langchain-ai/langserve/assets/3205522/86ce9c59-f8e4-4d08-9fa3-62030e0f521d" width="50%"/>
</p>

## Legacy Chains

Expand All @@ -246,12 +262,6 @@ However, some of the input schemas for legacy chains may be incomplete/incorrect
This can be fixed by updating the `input_schema` property of those chains in LangChain.
If you encounter any errors, please open an issue on THIS repo, and we will work to address it.

## Handling Authentication

If you need to add authentication to your server,
please reference FastAPI's [security documentation](https://fastapi.tiangolo.com/tutorial/security/)
and [middleware documentation](https://fastapi.tiangolo.com/tutorial/middleware/).

## Deployment

### Deploy to GCP
Expand All @@ -273,6 +283,13 @@ Except for these limitations, we expect the API endpoints, the playground and an

## Advanced

## Handling Authentication

If you need to add authentication to your server,
please reference FastAPI's [security documentation](https://fastapi.tiangolo.com/tutorial/security/)
and [middleware documentation](https://fastapi.tiangolo.com/tutorial/middleware/).


### Files

LLM applications often deal with files. There are different architectures
Expand Down Expand Up @@ -386,12 +403,12 @@ type Widget = {
};
```


#### File Upload Widget

Allows creation of a file upload input in the UI playground for files
that are uploaded as base64 encoded strings. Here's the full [example](https://github.com/langchain-ai/langserve/tree/main/examples/file_processing).


Snippet:

```python
Expand All @@ -413,3 +430,9 @@ class FileProcessingRequest(CustomUserType):
num_chars: int = 100

```

Example widget:

<p align="center">
<img src="https://github.com/langchain-ai/langserve/assets/3205522/52199e46-9464-4c2e-8be8-222250e08c3f" width="50%"/>
</p>
28 changes: 23 additions & 5 deletions examples/configurable_chain/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,32 @@
)
chain = prompt | model | StrOutputParser()

# Add routes requires you to specify which config keys are accepted
# specifically, you must accept `configurable` as a config key.
add_routes(app, chain, path="/configurable_temp", config_keys=["configurable"])
add_routes(app, chain, path="/configurable_temp")


###############################################################################
# EXAMPLE 2: Configure fields based on Request metadata #
# EXAMPLE 2: Configure prompt based on RunnableConfig #
###############################################################################
configurable_prompt = PromptTemplate.from_template(
"tell me a joke about {topic}."
).configurable_alternatives(
ConfigurableField(
id="prompt",
name="Prompt",
description="The prompt to use. Must contain {topic}.",
),
default_key="joke",
fact=PromptTemplate.from_template(
"tell me a fact about {topic} in {language} language."
),
)
prompt_chain = configurable_prompt | model | StrOutputParser()

add_routes(app, prompt_chain, path="/configurable_prompt")


###############################################################################
# EXAMPLE 3: Configure fields based on Request metadata #
###############################################################################


Expand Down Expand Up @@ -96,7 +115,6 @@ def fetch_api_key_from_header(config: Dict[str, Any], req: Request) -> Dict[str,
app,
dynamic_auth_chain,
path="/auth_from_header",
config_keys=["configurable"],
per_req_config_modifier=fetch_api_key_from_header,
)

Expand Down
Loading

0 comments on commit ab00b6c

Please sign in to comment.