Skip to content

Commit

Permalink
Add Custom Client example to the docs (#435)
Browse files Browse the repository at this point in the history
* WIP

* Add custom client example to docs

* Polishing

* Minor doc changes

* Merge remote-tracking branch 'origin/main' into 424-write-documentation-on-how-to-create-a-custom-client-and-make-it-work-with-the-fastapi-provider
  • Loading branch information
harishmohanraj authored Oct 21, 2024
1 parent 2c34f1b commit 0b3e46e
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 91 deletions.
2 changes: 1 addition & 1 deletion docs/docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ search:
- [FastAPI](user-guide/ui/fastapi/basics.md)
- [Adapters](user-guide/adapters/index.md)
- [FastAPI](user-guide/adapters/fastapi/index.md)
- [Nats.io](user-guide/adapters/nats/index.md)
- [FastAPI + Nats.io](user-guide/adapters/fastapi_nats/index.md)
- [Nats.io](user-guide/adapters/nats/index.md)
- [API-s](user-guide/api/index.md)
- [OpenAPI](user-guide/api/openapi/index.md)
- [Security](user-guide/api/security.md)
Expand Down
333 changes: 260 additions & 73 deletions docs/docs/en/user-guide/adapters/fastapi/index.md

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions docs/docs/en/user-guide/adapters/images/custom_fastapi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/docs/en/user-guide/adapters/images/mesop_fastapi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 12 additions & 13 deletions docs/docs/en/user-guide/adapters/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ Use the [**`FastAPIAdapter`**](../../api/fastagency/adapters/fastapi/FastAPIAdap

[Learn more about **FastAPI adapter**](./fastapi/)

### FastAPI + Nats.io

The [**`FastAPIAdapter`**](../../api/fastagency/adapters/fastapi/FastAPIAdapter.md) + [**`NatsAdapter`**](../../api/fastagency/adapters/nats/NatsAdapter.md) in FastAgency offers the most scalable setup by combining the power of the [**FastAPI**](https://fastapi.tiangolo.com/){target="_blank"} framework for building and exposing workflows as REST APIs with the [**NATS.io MQ**](https://nats.io/){target="_blank"} message broker for scalable and asynchronous communication. This setup is the preferred way for running large workloads in production.

#### When to Use the FastAPI + NATS.io Adapter

- **Custom Client Applications**: If you want to build your **own client applications** that interact with your FastAgency workflows using REST APIs, this adapter provides greater flexibility and control over the client-side implementation.
- **High User Demand**: When your application needs to handle a large number of users or messages and requires high scalability, the FastAPI + NATS Adapter is an excellent choice. It is well-suited for building **scalable custom chat applications for larger companies or external customers**.
- **Conversation Auditing**: If you need the ability to **audit conversations**, the NATS Adapter provides the necessary infrastructure to enable this feature.

[Learn more about **FastAPI + NATS.io adapter**](./fastapi_nats/)

### Nats.io

Utilize the [**`NatsAdapter`**](../../api/fastagency/adapters/nats/NatsAdapter.md) to use [**NATS.io MQ**](https://nats.io/){target="_blank"} message broker for highly-scalable, production-ready setup.
Expand All @@ -40,16 +52,3 @@ Utilize the [**`NatsAdapter`**](../../api/fastagency/adapters/nats/NatsAdapter.m


[Learn more about **NATS.io adapter**](./nats/)


### FastAPI + Nats.io

The [**`FastAPIAdapter`**](../../api/fastagency/adapters/fastapi/FastAPIAdapter.md) + [**`NatsAdapter`**](../../api/fastagency/adapters/nats/NatsAdapter.md) in FastAgency offers the most scalable setup by combining the power of the [**FastAPI**](https://fastapi.tiangolo.com/){target="_blank"} framework for building and exposing workflows as REST APIs with the [**NATS.io MQ**](https://nats.io/){target="_blank"} message broker for scalable and asynchronous communication. This setup is the preferred way for running large workloads in production.

#### When to Use the FastAPI + NATS.io Adapter

- **Custom Client Applications**: If you want to build your **own client applications** that interact with your FastAgency workflows using REST APIs, this adapter provides greater flexibility and control over the client-side implementation.
- **High User Demand**: When your application needs to handle a large number of users or messages and requires high scalability, the FastAPI + NATS Adapter is an excellent choice. It is well-suited for building **scalable custom chat applications for larger companies or external customers**.
- **Conversation Auditing**: If you need the ability to **audit conversations**, the NATS Adapter provides the necessary infrastructure to enable this feature.

[Learn more about **FastAPI + NATS.io adapter**](./fastapi_nats/)
2 changes: 1 addition & 1 deletion docs/docs/navigation_template.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ search:
- [FastAPI](user-guide/ui/fastapi/basics.md)
- [Adapters](user-guide/adapters/index.md)
- [FastAPI](user-guide/adapters/fastapi/index.md)
- [Nats.io](user-guide/adapters/nats/index.md)
- [FastAPI + Nats.io](user-guide/adapters/fastapi_nats/index.md)
- [Nats.io](user-guide/adapters/nats/index.md)
- [API-s](user-guide/api/index.md)
- [OpenAPI](user-guide/api/openapi/index.md)
- [Security](user-guide/api/security.md)
Expand Down
152 changes: 152 additions & 0 deletions docs/docs_src/getting_started/fastapi/main_custom_fastapi_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import os
from typing import Any

from autogen.agentchat import ConversableAgent
from fastapi import FastAPI
from fastapi.responses import HTMLResponse

from fastagency import UI
from fastagency.adapters.fastapi import FastAPIAdapter
from fastagency.runtimes.autogen import AutoGenWorkflows

html = """
<!DOCTYPE html>
<html>
<head>
<title>FastAgency Chat App</title>
</head>
<body>
<h1>FastAgency Chat App</h1>
<div id="workflows"></div>
<ul id="messages"></ul>
<script>
const API_URL = 'http://0.0.0.0:8008/fastagency';
const WS_URL = 'ws://0.0.0.0:8008/fastagency/ws'; // nosemgrep
let socket;
async function fetchWorkflows() {
const response = await fetch(`${API_URL}/discovery`);
const workflows = await response.json();
const container = document.getElementById('workflows');
workflows.forEach(workflow => {
const button = document.createElement('button');
button.textContent = workflow.description;
button.onclick = () => startWorkflow(workflow.name);
container.appendChild(button);
});
}
async function startWorkflow(name) {
const payload = {
workflow_name: name,
workflow_uuid: generateUUID(),
user_id: null, // Set to null for single-user applications; otherwise, provide the appropriate user ID
params: {}
};
const response = await fetch(`${API_URL}/initiate_workflow`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const workflowJson = await response.json();
connectWebSocket(workflowJson);
}
function connectWebSocket(workflowJson) {
socket = new WebSocket(WS_URL);
socket.onopen = () => {
const initMessage = {
name: workflowJson.name,
workflow_uuid: workflowJson.workflow_uuid,
user_id: workflowJson.user_id,
params: {}
};
socket.send(JSON.stringify(initMessage));
};
socket.onmessage = (event) => handleMessage(JSON.parse(event.data));
}
function handleMessage(message) {
const messagesList = document.getElementById('messages');
const li = document.createElement('li');
if (message.type === 'text_input') {
const response = prompt(message.content.prompt);
socket.send(response);
li.textContent = `${message.sender} -> ${message.recipient}: ${message.content.prompt}`;
} else {
li.textContent = `${message.sender} -> ${message.recipient}: ${message.content?.body || message?.type || JSON.stringify(message)}`;
}
messagesList.appendChild(li);
}
fetchWorkflows();
// Helper function for generating UUID
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
if (c === 'x') {
return (Math.random() * 16 | 0).toString(16);
} else {
return (Math.random() * 16 | 0 & 0x3 | 0x8).toString(16);
}
});
}
</script>
</body>
</html>
"""

llm_config = {
"config_list": [
{
"model": "gpt-4o-mini",
"api_key": os.getenv("OPENAI_API_KEY"),
}
],
"temperature": 0.8,
}

wf = AutoGenWorkflows()

@wf.register(name="simple_learning", description="Student and teacher learning chat")
def simple_workflow(ui: UI, params: dict[str, Any]) -> str:
initial_message = ui.text_input(
sender="Workflow",
recipient="User",
prompt="I can help you learn about mathematics. What subject you would like to explore?",
)

student_agent = ConversableAgent(
name="Student_Agent",
system_message="You are a student willing to learn.",
llm_config=llm_config,
# human_input_mode="ALWAYS",
)
teacher_agent = ConversableAgent(
name="Teacher_Agent",
system_message="You are a math teacher.",
llm_config=llm_config,
# human_input_mode="ALWAYS",
)

chat_result = student_agent.initiate_chat(
teacher_agent,
message=initial_message,
summary_method="reflection_with_llm",
max_turns=5,
)

return chat_result.summary # type: ignore[no-any-return]

adapter = FastAPIAdapter(provider=wf)

app = FastAPI()
app.include_router(adapter.router)

@app.get("/")
async def get() -> HTMLResponse:
return HTMLResponse(html)


# start the provider with the following command
# uvicorn main_custom_fastapi_client:app --host 0.0.0.0 --port 8008 --reload
6 changes: 5 additions & 1 deletion docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,11 @@ markdown_extensions:
- extra
- admonition # !!! note blocks support
- pymdownx.details # admonition collapsible
- pymdownx.superfences # highlight code syntax
- pymdownx.superfences: # highlight code syntax
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.highlight:
anchor_linenums: true # allows link to codeline
- pymdownx.inlinehilite # inline code highlighting `#!python <code>`
Expand Down

0 comments on commit 0b3e46e

Please sign in to comment.