Skip to content

Commit

Permalink
Improvements to Framework pages and images
Browse files Browse the repository at this point in the history
  • Loading branch information
anant-writer committed Jun 3, 2024
1 parent 5f1cda2 commit cc69c8e
Show file tree
Hide file tree
Showing 23 changed files with 268 additions and 257 deletions.
52 changes: 33 additions & 19 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,35 +47,39 @@ 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.

### 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 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.

Expand All @@ -78,12 +98,6 @@ 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:

```python
Expand Down
57 changes: 30 additions & 27 deletions docs/framework/application-state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ Each session is assigned a unique application state by the Framework.

## 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 Down Expand Up @@ -58,6 +62,31 @@ To keep certain state elements private (back-end-only), prefix them with an unde

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

## Managing files and binary data

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 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

# Initialize state with various data types
wf.init_state({
# Reference a file by its filesystem path
"sales_spreadsheet": wf.pack_file("sales_spreadsheet.xlsx"),

# Use a file-like object that implements a .read() method
"main_image": wf.pack_file(image_file, mime_type="image/jpeg"),

# Convert raw bytes specifying a MIME type
"my_bytes": wf.pack_bytes(b"\x31\x33\x33\x37", mime_type="text/plain"),

# Directly assign raw bytes without a MIME type
"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.
Expand All @@ -84,29 +113,3 @@ The front-end cannot directly display complex data types such as Pandas datafram
Pandas dataframes are converted to JSON and can be used in _Dataframe_ components.
</Tab>
</Tabs>


## Managing files and binary data

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 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

# Initialize state with various data types
wf.init_state({
# Reference a file by its filesystem path
"sales_spreadsheet": wf.pack_file("sales_spreadsheet.xlsx"),

# Use a file-like object that implements a .read() method
"main_image": wf.pack_file(image_file, mime_type="image/jpeg"),

# Convert raw bytes specifying a MIME type
"my_bytes": wf.pack_bytes(b"\x31\x33\x33\x37", mime_type="text/plain"),

# Directly assign raw bytes without a MIME type
"my_raw_bytes": b"\x31\x33\x33\x37",
})
```
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 cc69c8e

Please sign in to comment.