Skip to content

Commit

Permalink
docs: add an example (#5)
Browse files Browse the repository at this point in the history
* docs: add example

Signed-off-by: Isac Byeonghoon Yoo <[email protected]>

* docs: update usage

Signed-off-by: Isac Byeonghoon Yoo <[email protected]>

* docs: update usage

Signed-off-by: Isac Byeonghoon Yoo <[email protected]>

---------

Signed-off-by: Isac Byeonghoon Yoo <[email protected]>
  • Loading branch information
isac322 authored Dec 20, 2023
1 parent ce4739e commit 453f33f
Show file tree
Hide file tree
Showing 5 changed files with 1,024 additions and 0 deletions.
8 changes: 8 additions & 0 deletions example/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM python:3.11-slim as build
WORKDIR /opt/app
EXPOSE 8000
ENTRYPOINT ["poetry", "run", "python", "/opt/app/main.py"]

COPY poetry.lock pyproject.toml main.py ./
RUN pip install -U poetry \
&& poetry install --no-root --sync
21 changes: 21 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# PlugBear Python SDK Example (FastAPI)

## Prerequisites

- Docker

## Usage

This will create a math tutor AI.
You can make a query on any integrated channel, like this: ``@PlugBear I need to solve the equation `3x + 11 = 14`. Can you help me?``.

```shell
docker build . -t plugbear-python-sdk-example
docker run --rm -ti \
-p 8000:8000 \
-e PLUGBEAR_API_KEY="YOUR.PLUGBEAR.API.KEY" \
-e OPENAI_API_KEY="YOUR.OPENAI.API.KEY" \
plugbear-python-sdk-example
```

You can also existing assistant by passing `OPENAI_ASSISTANT_ID` environment to `docker run`.
90 changes: 90 additions & 0 deletions example/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from __future__ import annotations

import asyncio
import contextlib
import os
from collections.abc import AsyncGenerator

from fastapi import FastAPI
from openai import AsyncOpenAI
from openai.pagination import AsyncCursorPage
from openai.types.beta.threads import MessageContentText, ThreadMessage

import plugbear.fastapi


# create a OpenAI Assistant if the user does not enter an OpenAi Assistant ID.
async def _get_openai_assistant_id(client: AsyncOpenAI) -> str:
try:
return os.environ["OPENAI_ASSISTANT_ID"]
except KeyError:
assistant = await client.beta.assistants.create(
name="Math Tutor",
instructions="You are a personal math tutor. Write and run code to answer math questions.",
tools=[{"type": "code_interpreter"}],
model="gpt-4-1106-preview",
)
return assistant.id


openai_client = AsyncOpenAI(api_key=os.environ["OPENAI_API_KEY"])
openai_assistant_id = asyncio.get_event_loop().run_until_complete(_get_openai_assistant_id(openai_client))


async def openai_assistant(request: plugbear.fastapi.Request) -> str:
thread = await openai_client.beta.threads.create()

joined_msg = "\n".join(m.content for m in request.messages)
await openai_client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=joined_msg,
)

run = await openai_client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=openai_assistant_id,
instructions="Please address the user as Jane Doe. The user has a premium account.",
)

while run.status != "completed":
await asyncio.sleep(1)
run = await openai_client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)

messages = await openai_client.beta.threads.messages.list(thread_id=thread.id)
print(messages)
return _join_assistant_messages(messages)


def _join_assistant_messages(m: AsyncCursorPage[ThreadMessage]) -> str:
messages: list[str] = []
for data in m.data:
if data.role != "assistant":
continue

for content in data.content:
if not isinstance(content, MessageContentText):
continue
messages.append(content.text.value)

return "\n".join(messages)


@contextlib.asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
await plugbear.fastapi.register(
app,
llm_func=openai_assistant,
api_key=os.environ["PLUGBEAR_API_KEY"],
endpoint=os.getenv("PLUGBEAR_ENDPOINT", default="/plugbear"),
)

yield


app = FastAPI(lifespan=lifespan)

if __name__ == "__main__":
import uvicorn

uvicorn.run(app, host="0.0.0.0", port=int(os.getenv("PORT", default=8000)))
Loading

0 comments on commit 453f33f

Please sign in to comment.