Skip to content
This repository has been archived by the owner on Oct 19, 2023. It is now read-only.

Commit

Permalink
Merge pull request #133 from jina-ai/feat-secrets
Browse files Browse the repository at this point in the history
feat: support secrets
  • Loading branch information
deepankarm committed Jul 27, 2023
2 parents 6b2fd26 + f75922c commit 9e08db8
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 31 deletions.
67 changes: 66 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ langchain-serve currently wraps following apps as a service to be deployed on Ji
- 🔑 Protect your APIs with [API authorization](#-authorize-your-apis) using Bearer tokens.
- 📄 Swagger UI, and OpenAPI spec included with your APIs.
- ⚡️ Serverless, autoscaling apps that scales automatically with your traffic.
- 🗝️ Secure handling of secrets and environment variables.
- 📁 Persistent storage (EFS) mounted on your app for your data.
- 📊 Builtin logging, monitoring, and traces for your APIs.
- 🤖 No need to change your code to manage APIs, or manage dockerfiles, or worry about infrastructure!
Expand Down Expand Up @@ -369,7 +370,71 @@ lc-serve deploy jcloud --app endpoints:app

</details>

---
## 🗝️ Using Secrets during Deployment

You can use secrets during app deployment by passing a secrets file to deployment with the `--secrets` flag. The secrets file should be a `.env` file containing the secrets.

```bash
lcserve deploy jcloud app --secrets .env
```

<details>
<summary>Show details</summary>

Let's take an example of a simple app that uses `OPENAI_API_KEY` stored as secrets.

This app directory contains the following files:

```
.
├── main.py # The app
├── jcloud.yml # JCloud deployment config file
├── README.md # This README file
├── requirements.txt # The requirements file for the app
└── secrets.env # The secrets file containing the redis credentials
```

> **Note**
> `secret.env` in this directory is a dummy file. You should replace it with your own secrets after creating a Redis instance. (For example with [Upstash](https://upstash.com/)), such as:
```text
OPENAI_API_KEY=sk-xxx
```

`main.py` will look like:

```python
# main.py
from lcserve import serving
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI

prompt = PromptTemplate(
input_variables=["subject"],
template="Write me a short poem about {subject}?",
)


@serving(openai_tracing=True)
def poem(subject: str, **kwargs):
tracing_handler = kwargs.get("tracing_handler")

chat = ChatOpenAI(temperature=0.5, callbacks=[tracing_handler])
chain = LLMChain(llm=chat, prompt=prompt, callbacks=[tracing_handler])

return chain.run(subject)
```

In the above example, the app will use `OPENAI_API_KEY` provided by the secrets to interact with OpenAI.

Then you can deploy using the following command and interact with the deployed endpoint.

```bash
lc-serve deploy jcloud main --secrets secrets.env
```

</details>

## 💻 `lc-serve` CLI

Expand Down
86 changes: 66 additions & 20 deletions lcserve/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
get_uri,
list_apps_on_jcloud,
load_local_df,
patch_secret_on_jcloud,
remove_app_on_jcloud,
syncify,
update_requirements,
Expand Down Expand Up @@ -66,6 +67,7 @@ async def serve_on_jcloud(
config: str = None,
cors: bool = True,
env: str = None,
secret: str = None,
verbose: bool = False,
public: bool = False,
lcserve_app: bool = False,
Expand Down Expand Up @@ -94,25 +96,40 @@ async def serve_on_jcloud(
public=public,
)

# Get the flow dict
flow_dict = get_flow_dict(
module_str=module_str,
fastapi_app_str=fastapi_app_str,
jcloud=True,
port=8080,
name=name,
timeout=timeout,
app_id=app_id,
gateway_id=gateway_id,
is_websocket=is_websocket,
jcloud_config_path=config,
cors=cors,
env=env,
lcserve_app=lcserve_app,
)

# Deploy the app
app_id, _ = await deploy_app_on_jcloud(
flow_dict=get_flow_dict(
module_str=module_str,
fastapi_app_str=fastapi_app_str,
jcloud=True,
port=8080,
name=name,
timeout=timeout,
app_id=app_id,
gateway_id=gateway_id,
is_websocket=is_websocket,
jcloud_config_path=config,
cors=cors,
env=env,
lcserve_app=lcserve_app,
),
flow_dict=flow_dict,
app_id=app_id,
verbose=verbose,
)

# If secret is not None, create a secret and update the app
if secret is not None:
await patch_secret_on_jcloud(
flow_dict=flow_dict,
app_id=app_id,
secret=secret,
verbose=verbose,
)

# Show the app status
await get_app_status_on_jcloud(app_id=app_id)
return app_id

Expand All @@ -127,6 +144,7 @@ async def serve_babyagi_on_jcloud(
config: str = None,
cors: bool = True,
env: str = None,
secret: str = None,
verbose: bool = False,
public: bool = False,
):
Expand All @@ -149,6 +167,7 @@ async def serve_babyagi_on_jcloud(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
lcserve_app=True,
Expand All @@ -165,6 +184,7 @@ async def serve_autogpt_on_jcloud(
config: str = None,
cors: bool = True,
env: str = None,
secret: str = None,
verbose: bool = False,
public: bool = False,
):
Expand All @@ -186,6 +206,7 @@ async def serve_autogpt_on_jcloud(
platform=platform,
config=config,
env=env,
secret=secret,
cors=cors,
verbose=verbose,
public=public,
Expand All @@ -203,6 +224,7 @@ async def serve_pdf_qna_on_jcloud(
config: str = None,
cors: bool = True,
env: str = None,
secret: str = None,
verbose: bool = False,
public: bool = False,
):
Expand All @@ -218,6 +240,7 @@ async def serve_pdf_qna_on_jcloud(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
lcserve_app=True,
Expand All @@ -234,6 +257,7 @@ async def serve_pandas_ai_on_jcloud(
config: str = None,
cors: bool = True,
env: str = None,
secret: str = None,
verbose: bool = False,
public: bool = False,
):
Expand All @@ -249,6 +273,7 @@ async def serve_pandas_ai_on_jcloud(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
lcserve_app=True,
Expand All @@ -265,6 +290,7 @@ async def serve_slackbot_demo_on_jcloud(
config: str = None,
cors: bool = True,
env: str = None,
secret: str = None,
verbose: bool = False,
public: bool = False,
):
Expand All @@ -280,6 +306,7 @@ async def serve_slackbot_demo_on_jcloud(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
lcserve_app=True,
Expand Down Expand Up @@ -396,18 +423,25 @@ def upload_df_to_jcloud(module: str, name: str):
callback=validate_jcloud_config_callback,
show_default=False,
),
click.option(
'--cors',
is_flag=True,
help='Enable CORS.',
default=True,
show_default=True,
),
click.option(
'--env',
type=click.Path(exists=True),
help='Path to the environment file',
show_default=False,
),
click.option(
'--cors',
is_flag=True,
help='Enable CORS.',
default=True,
show_default=True,
'--secret',
'--secrets',
type=click.Path(exists=True),
help='Path to the secrets file (should be a .env file)',
show_default=False,
),
click.option(
'--verbose',
Expand Down Expand Up @@ -674,6 +708,7 @@ async def jcloud(
config,
cors,
env,
secret,
verbose,
public,
):
Expand All @@ -690,6 +725,7 @@ async def jcloud(
platform=platform,
config=config,
env=env,
secret=secret,
cors=cors,
verbose=verbose,
public=public,
Expand Down Expand Up @@ -717,6 +753,7 @@ async def babyagi(
config,
cors,
env,
secret,
verbose,
public,
):
Expand All @@ -730,6 +767,7 @@ async def babyagi(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
)
Expand All @@ -756,6 +794,7 @@ async def pdf_qna(
config,
cors,
env,
secret,
verbose,
public,
):
Expand All @@ -769,6 +808,7 @@ async def pdf_qna(
platform=platform,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
)
Expand All @@ -795,6 +835,7 @@ async def autogpt(
config,
cors,
env,
secret,
verbose,
public,
):
Expand All @@ -808,6 +849,7 @@ async def autogpt(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
)
Expand All @@ -834,6 +876,7 @@ async def pandas_ai(
config,
cors,
env,
secret,
verbose,
public,
):
Expand All @@ -847,6 +890,7 @@ async def pandas_ai(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
)
Expand All @@ -873,6 +917,7 @@ async def slackbot_demo(
config,
cors,
env,
secret,
verbose,
public,
):
Expand All @@ -886,6 +931,7 @@ async def slackbot_demo(
config=config,
cors=cors,
env=env,
secret=secret,
verbose=verbose,
public=public,
)
Expand Down
6 changes: 5 additions & 1 deletion lcserve/backend/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import uuid
from tempfile import NamedTemporaryFile
from typing import TYPE_CHECKING

Expand All @@ -6,7 +7,6 @@

import hubble


JINAAI_PREFIX = 'jinaai://'


Expand Down Expand Up @@ -50,3 +50,7 @@ def download_df(id: str, read_csv_kwargs={}) -> 'DataFrame':
df = pd.read_csv(id, **read_csv_kwargs)
df.columns = [col.strip('" ') for col in df.columns]
return df


def get_random_name():
return 'f-' + uuid.uuid4().hex[:6]

0 comments on commit 9e08db8

Please sign in to comment.