-
Notifications
You must be signed in to change notification settings - Fork 236
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of github.com:langchain-ai/langserve into main
- Loading branch information
Showing
17 changed files
with
645 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# File processing\n", | ||
"\n", | ||
"This client will be uploading a PDF file to the langserve server which will read the PDF and extract content from the first page." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's load the file in base64 encoding:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 18, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"import base64\n", | ||
"\n", | ||
"with open(\"sample.pdf\", \"rb\") as f:\n", | ||
" data = f.read()\n", | ||
"\n", | ||
"encoded_data = base64.b64encode(data).decode(\"utf-8\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Using raw requests" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 19, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"{'output': 'If you’re reading this you might be using LangServe 🦜🏓!\\n\\nThis is a sample PDF!\\n\\n\\x0c',\n", | ||
" 'callback_events': []}" | ||
] | ||
}, | ||
"execution_count": 19, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"import requests\n", | ||
"\n", | ||
"requests.post(\n", | ||
" \"http://localhost:8000/pdf/invoke/\", json={\"input\": {\"file\": encoded_data}}\n", | ||
").json()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Using the SDK" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 20, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from langserve import RemoteRunnable\n", | ||
"\n", | ||
"runnable = RemoteRunnable(\"http://localhost:8000/pdf/\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 21, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"'If you’re reading this you might be using LangServe 🦜🏓!\\n\\nThis is a sample PDF!\\n\\n\\x0c'" | ||
] | ||
}, | ||
"execution_count": 21, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"runnable.invoke({\"file\": encoded_data})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 22, | ||
"metadata": { | ||
"tags": [] | ||
}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"['If you’re reading this you might be using LangServe 🦜🏓!\\n\\nThis is a sample PDF!\\n\\n\\x0c',\n", | ||
" 'If you’re ']" | ||
] | ||
}, | ||
"execution_count": 22, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"runnable.batch([{\"file\": encoded_data}, {\"file\": encoded_data, \"num_chars\": 10}])" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.9.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"""Example that shows how to upload files and process files in the server. | ||
This example uses a very simple architecture for dealing with file uploads | ||
and processing. | ||
The main issue with this approach is that processing is done in | ||
the same process rather than offloaded to a process pool. A smaller | ||
issue is that the base64 encoding incurs an additional encoding/decoding | ||
overhead. | ||
This example also specifies a "base64file" widget, which will create a widget | ||
allowing one to upload a binary file using the langserve playground UI. | ||
""" | ||
import base64 | ||
|
||
from fastapi import FastAPI | ||
from langchain.document_loaders.blob_loaders import Blob | ||
from langchain.document_loaders.parsers.pdf import PDFMinerParser | ||
from langchain.schema.runnable import RunnableLambda | ||
from pydantic import Field | ||
|
||
from langserve import CustomUserType, add_routes | ||
|
||
app = FastAPI( | ||
title="LangChain Server", | ||
version="1.0", | ||
description="Spin up a simple api server using Langchain's Runnable interfaces", | ||
) | ||
|
||
|
||
# ATTENTION: Inherit from CustomUserType instead of BaseModel otherwise | ||
# the server will decode it into a dict instead of a pydantic model. | ||
class FileProcessingRequest(CustomUserType): | ||
"""Request including a base64 encoded file.""" | ||
|
||
# The extra field is used to specify a widget for the playground UI. | ||
file: str = Field(..., extra={"widget": {"type": "base64file"}}) | ||
num_chars: int = 100 | ||
|
||
|
||
def _process_file(request: FileProcessingRequest) -> str: | ||
"""Extract the text from the first page of the PDF.""" | ||
content = base64.b64decode(request.file.encode("utf-8")) | ||
blob = Blob(data=content) | ||
documents = list(PDFMinerParser().lazy_parse(blob)) | ||
content = documents[0].page_content | ||
return content[: request.num_chars] | ||
|
||
|
||
add_routes( | ||
app, | ||
RunnableLambda(_process_file).with_types(input_type=FileProcessingRequest), | ||
config_keys=["configurable"], | ||
path="/pdf", | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
import uvicorn | ||
|
||
uvicorn.run(app, host="localhost", port=8000) |
Oops, something went wrong.