Skip to content

Commit

Permalink
Fixed formatting and QA on tutorials
Browse files Browse the repository at this point in the history
  • Loading branch information
anant-writer authored and FabienArcellier committed Jun 14, 2024
1 parent 3238b96 commit 7b4c660
Show file tree
Hide file tree
Showing 84 changed files with 769 additions and 721 deletions.
4 changes: 2 additions & 2 deletions docs/components/component_page.mdx.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ mode: "wide"
{% if fields %}
## Fields

<table>
<table className="componentFields">
<thead>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th class="desc">Description</th>
<th>Options</th>
</thead>
<tbody>
Expand Down
66 changes: 40 additions & 26 deletions docs/framework/ai-module.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,23 @@
title: "Writer AI module"
---

This module leverages the Writer SDK to enable applications to interact with large language models (LLMs) in chat or text completion formats. It provides tools to manage conversation states and to dynamically interact with LLMs using both synchronous and asynchronous methods.
This module leverages the [Writer Python SDK](https://pypi.org/project/writer-sdk/) to enable applications to interact with large language models (LLMs) in chat or text completion formats. It provides tools to manage conversation states and to dynamically interact with LLMs using both synchronous and asynchronous methods.

## Getting your API key
To utilize the Writer AI module, you'll need to configure the `WRITER_API_KEY` environment variable with an API key obtained from AI Studio. Here is a detailed [guide](/api-guides/quickstart) to setup up this key. You will need to select an **API** app under **Developer tools**

Once you have your API key, set it as an environment variable on your system:
<CodeGroup>
``` bash For macOS and Linux
export WRITER_API_KEY=your_api_key_here
```
```bash For Windows
set WRITER_API_KEY=your_api_key_here
```
</CodeGroup>
You can manage your environment variables using methods that best suit your setup, such as employing tools like [python-dotenv](https://pypi.org/project/python-dotenv/).

Furthermore, when deploying an application with `writer deploy`, the `WRITER_API_KEY` environment variable is automatically configured with the API key specified during the deployment process.

## Conversation class
The `Conversation` class manages LLM communications within a chat framework, storing the conversation history and handling the interactions.
Expand Down Expand Up @@ -31,37 +47,41 @@ A `Conversation` can be initialized with either a system prompt or a list of pre


```python
# Initialize with a system prompt
conversation = Conversation("You assist Chinese-speaking clients with their questions")
# Initialize with a system prompt for a Financial Analyst specializing in balance sheets
conversation = Conversation("You assist clients with analyzing and understanding their balance sheets")

# Initialize with a history of messages
# Initialize with a history of messages related to balance sheet queries
history = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi, how can I help?"}
{"role": "user", "content": "Can you explain the liabilities section?"},
{"role": "assistant", "content": "Certainly! Liabilities are legally binding obligations payable to another entity."}
]

conversation = Conversation(history)

# Initialize with a configuration
config = {'max_tokens': 150, 'temperature': 0.7}
conversation = Conversation("You are a social media expert in the financial industry", config=config)
# Initialize with a configuration suitable for financial analysis discussions
config = {'max_tokens': 200, 'temperature': 0.5}
conversation = Conversation("You provide detailed insights into balance sheet components", config=config)
```

### Adding messages to conversation
Messages can be added to a `Conversation` instance using the `+` operator or the `add` method.

```python
# Using the `+` operator
conversation += {"role": "user", "content": "What's the weather like?"}
# Using the `+` operator to add a balance sheet-related query
conversation += {"role": "user", "content": "Can you break down the assets section of the balance sheet?"}

# Using the `add` method
conversation.add(role="user", content="What's the weather like?")
# Using the `add` method to add a balance sheet-related query
conversation.add(role="user", content="How should I interpret the equity section?")
```

Addition to `Conversation` only works against `dict` objects that contain `"role"` and `"content"` items. Providing a `"chunk": True` flag into the object will merge it against the last message appending `"content"` and replacing other values.
Addition to `Conversation` only works against `dict` objects that contain `"role"` and `"content"` items. Providing a `"chunk": True` flag into the object will merge it against the last message - appending `"content"` and replacing other values.

### Completing and streaming Conversations
<Tip>
When utilizing the `stream_complete` feature, the initial chunk of data returned by the stream is not specifically marked as a "chunk." This is intentional, allowing for the seamless integration of this first piece into the conversation history when appended using the + operator.
</Tip>

The `complete` and `stream_complete` methods facilitate interaction with the LLM based on the accumulated messages and configuration. These methods execute calls to generate responses and return them in form of a message object, but do not alter the conversation's `messages` list, allowing you to validate or modify the output before deciding to add it to the history.
The `complete` and `stream_complete` methods facilitate interaction with the LLM based on the accumulated messages and configuration. These methods execute calls to generate responses and return them in the form of a message object, but do not alter the conversation's `messages` list, allowing you to validate or modify the output before deciding to add it to the history.

<CodeGroup>
```python complete
Expand All @@ -78,31 +98,25 @@ for chunk in conversation.stream_complete():
```
</CodeGroup>



<Tip>
First chunk of `stream_complete` is not flagged. When using `stream_complete`, the first chunk returned by the stream is not flagged explicitly as a "chunk." This behavior is by design, to seamlessly add this initial chunk into the conversation history if it is appended using the `+` operator.
</Tip>

Instance-wide configuration parameters can be complemented or overriden on individual call's level, if a `data` dictionary is provided to the method:
Instance-wide configuration parameters can be complemented or overriden on individual call's level, if a `config` dictionary is provided to the method:

```python
# Overriding configuration for a specific call
response = conversation.complete(data={'max_tokens': 200, 'temperature': 0.5})
response = conversation.complete(config={'max_tokens': 200, 'temperature': 0.5})
```

## Text completions without a conversation state
These `complete` and `stream_complete` methods are designed for one-off text completions without the need to manage a conversation state. They return the model's response as a string. Each function accepts a `data` dictionary allowing call-specific configurations.
These `complete` and `stream_complete` methods are designed for one-off text completions without the need to manage a conversation state. They return the model's response as a string. Each function accepts a `config` dictionary allowing call-specific configurations.

<CodeGroup>
```python complete
# Using `complete` for a single completion
text_response = complete("Explore the benefits of AI.", data={'temperature': 0.3})
text_response = complete("Explore the benefits of AI.", config={'temperature': 0.3})
print("Completion:", text_response)
```
```python stream_complete
# Using `stream_complete` for streamed text completions
for text_chunk in stream_complete("Explore the benefits of AI.", data={'temperature': 0.3}):
for text_chunk in stream_complete("Explore the benefits of AI.", config={'temperature': 0.3}):
print("Streamed Text:", text_chunk)
```
</CodeGroup>
Expand Down
81 changes: 42 additions & 39 deletions docs/framework/application-state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ title: "Application state"

Each session is assigned a unique application state by the Framework.

## Initialising state
## Initializing state

To set the initial application state, use the `wf.init_state()` method with a dictionary argument. **All user sessions will start with a clone of this initial state**.
To set the initial application state, use the `wf.init_state()` method with a dictionary argument.

<Tip>
All user sessions will start with a clone of this initial state.
</Tip>

```py
import writer as wf
Expand All @@ -26,7 +30,7 @@ In the above example, each session begins with a `counter` at 0. As users intera

To access the `counter` value in the Builder, use @{counter}.

### Managing Nested State Elements
### Managing nested state elements

To include nested elements in your state, use nested dictionaries:

Expand All @@ -44,53 +48,25 @@ You can reference nested elements in the Builder as `@{my_app.title}`.

### Backend-only state elements

By default, all of the elements in the session state are sent to the frontend.
By default, all of the elements in the session state are sent to the front-end.

<Warning>
All state elements are transmitted to the frontend by default, regardless of their visibility in the user interface.
All state elements are transmitted to the front-end by default, regardless of their visibility in the user interface.
</Warning>

To keep certain state elements private (backend-only), prefix them with an underscore `_`. This is useful in several scenarios:
To keep certain state elements private (back-end-only), prefix them with an underscore `_`. This is useful in several scenarios:

1. When data synchronization to the frontend is unnecessary.
2. When data cannot be serialized for the frontend, such as database connections.
1. When data synchronization to the front-end is unnecessary.
2. When data cannot be serialized for the front-end, such as database connections.
3. When data is sensitive to the specific session and should remain confidential.

These elements remain in the backend and cannot be accessed from the Builder.

## Handling non-standard data types

The frontend cannot directly display complex data types such as Pandas dataframes or Matplotlib figures. Such objects must be serialized before being sent.

<Tabs>
<Tab title="Matplotlib Figures">
Matplotlib figures are converted to PNG data URLs, which can be shown using a standard _Image_ component.

```python
wf.init_state({
"my_matplotlib_fig": fig,
})
```

The element can be used in an _Image_ component in Builder by setting the source to `@{my_matplotlib_fig}`. Alternatively, as data inside a _File Download_ component.
</Tab>
<Tab title="Plotly Graphs">
Plotly graphs are converted to Plotly JS specifications, using JSON. They can be used in _Plotly Graph_ components.
</Tab>
<Tab title="Altair Charts">
Altair charts are converted to Vega Lite specifications, based on JSON. They can be used in _Vega Lite Chart_ components.
</Tab>
<Tab title="Pandas Dataframes">
Pandas dataframes are converted to JSON and can be used in _Dataframe_ components.
</Tab>
</Tabs>

These elements remain in the back-end and cannot be accessed from the Builder.

## Managing files and binary data

In components where Builder interfaces with external data, such as images, it often requires the use of data URLs. The source for an _Image_ component, for example, can be a standard URL or a data URL.
In components where the Builder interfaces with external data, such as images, it often requires the use of data URLs. The source for an _Image_ component, for example, can be a standard URL or a data URL.

Packing Files and Binary Data: Files and binary data can be converted to data URLs before they are sent to the frontend. Use `wf.pack_file()` and `wf.pack_bytes()` for this purpose. The `mime_type` argument, while optional, specifies the media type, helping the browser to correctly handle the data.
Packing Files and Binary Data: Files and binary data can be converted to data URLs before they are sent to the front-end. Use `wf.pack_file()` and `wf.pack_bytes()` for this purpose. The `mime_type` argument, while optional, specifies the media type, helping the browser to correctly handle the data.

```python
import writer as wf
Expand All @@ -110,3 +86,30 @@ wf.init_state({
"my_raw_bytes": b"\x31\x33\x33\x37",
})
```

## Handling non-standard data types

The front-end cannot directly display complex data types such as Pandas dataframes or Matplotlib figures. Such objects must be serialized before being sent.

<Tabs>
<Tab title="Matplotlib figures">
Matplotlib figures are converted to PNG data URLs, which can be shown using a standard _Image_ component.

```python
wf.init_state({
"my_matplotlib_fig": fig,
})
```

The element can be used in an _Image_ component in the Builder by setting the source to `@{my_matplotlib_fig}`. Alternatively, as data inside a _File Download_ component.
</Tab>
<Tab title="Plotly graphs">
Plotly graphs are converted to Plotly JS specifications, using JSON. They can be used in _Plotly Graph_ components.
</Tab>
<Tab title="Altair charts">
Altair charts are converted to Vega Lite specifications, based on JSON. They can be used in _Vega Lite Chart_ components.
</Tab>
<Tab title="Pandas dataframes">
Pandas dataframes are converted to JSON and can be used in _Dataframe_ components.
</Tab>
</Tabs>
6 changes: 3 additions & 3 deletions docs/framework/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Authentication"
---

The Writer framework authentication module allows you to restrict access to your application.
The Writer Framework authentication module allows you to restrict access to your application.

Framework will be able to authenticate a user through an identity provider such as Google, Microsoft, Facebook, Github, Auth0, etc.

Expand Down Expand Up @@ -76,7 +76,7 @@ writer.serve.register_auth(oidc)

### Use pre-configured OIDC

Writer framework provides pre-configured OIDC providers. You can use them directly in your application.
The Writer Framework provides pre-configured OIDC providers. You can use them directly in your application.

| Provider | Function | Description |
| -------- | ------------------------ | --------------------------------------------------------------------------------------- |
Expand Down Expand Up @@ -187,7 +187,7 @@ writer.serve.register_auth(oidc, callback=callback)

The default authentication error page look like this:

<img src="./framework/images/auth_unauthorized_default.png" />
<img src="/framework/images/auth_unauthorized_default.png" />

_streamsync.auth.Unauthorized_

Expand Down
8 changes: 4 additions & 4 deletions docs/framework/backend-driven-ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
title: "Backend-driven UI"
---

Framework facilitates backend-initiated user interface modifications. These changes are made possible through **Code-Managed Components** (CMCs), distinct from *Builder-Managed Components* (BMCs).
Framework facilitates backend-initiated user interface modifications. These changes are made possible through **Code-Managed Components** (CMCs), distinct from the *Builder-Managed Components* (BMCs).

CMCs, unlike BMCs, are dynamically created and modified via backend code, and cannot be edited (but still can be viewed) within the application builder. It's important to also note that CMCs do not persist in your application's `ui.json` file and exist only during the application runtime, supporting dynamic UI adjustments.
CMCs, unlike BMCs, are dynamically created and modified via back-end code, and cannot be edited (but still can be viewed) within the application builder. It's important to also note that CMCs do not persist in your application's `ui.json` file and exist only during the application runtime, supporting dynamic UI adjustments.

<Note>
To summarise:

**CMC** – Code-Managed Component
- created via **application backend**;
- created via **application back-end**;
- **cannot be edited** in builder;
- is **not saved** to `ui.json`.

Expand Down Expand Up @@ -98,7 +98,7 @@ with ui.find(container):

### Component methods

UI manager contains methods linked to each frontend component. For example, in previous code snippets we provide a `ui.Text` method, which is used for creating [Text components](https://www.streamsync.cloud/component-list.html#text).
UI manager contains methods linked to each front-end component. For example, in previous code snippets we provide a `ui.Text` method, which is used for creating [Text components](https://www.streamsync.cloud/component-list.html#text).

This method expects `content: dict` as first argument, which enables you to set the field properties of the component, through corresponding keys:
```python
Expand Down
2 changes: 1 addition & 1 deletion docs/framework/backend-initiated-actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def handle_file_download(state):

## Adding a notification

![Notifications](./images/backend-initiated-actions.notifications.png)
![Notifications](/framework/images/backend-initiated-actions.notifications.png)

Framework adds notifications when a runtime error takes place. You can add your own notifications using the `add_notification` method, which takes the `type`, `title` and `message` arguments. `type` must be one of `error`, `warning`, `info`, `success`.

Expand Down
Loading

0 comments on commit 7b4c660

Please sign in to comment.