Skip to content

Commit

Permalink
draft
Browse files Browse the repository at this point in the history
  • Loading branch information
yalu4 committed Oct 17, 2023
1 parent aca03d4 commit a979108
Show file tree
Hide file tree
Showing 24 changed files with 410 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Create and Use Your Own Custom Strong Type Connection
In this doc, I will guide you through how to use custom strong type connection. Compared with custom connection, using custom strong type connection would be more user friendly since when creating a custom strong type connection, you do not need to fill in the connection keys. The connection keys can be auto filled, all you need to do is fill in the values and create!

## Prerequisites
- Install promptflow package.

```bash
# Eventually only pip install promptflow==0.1.0b8
pip install "promptflow==0.0.107761800" --extra-index-url https://azuremlsdktestpypi.azureedge.net/promptflow
```

## Configure your own custom strong type connection in your tool package
You can take this [file](../../../examples/tools/tool-package-quickstart/my_tool_package/tools/my_tool_with_custom_strong_type_connection.py) as an example to peek what a tool using your custom strong type connection is like.
Configure your custom strong type connection like this:
```python
from promptflow.connections import CustomStrongTypeConnection
from promptflow.contracts.types import Secret


class MyCustomConnection(CustomStrongTypeConnection):
"""My custom strong type connection.
:param api_key: The api key.
:type api_key: String
:param api_base: The api base.
:type api_base: String
"""
api_key: Secret
api_url: str = "This is a fake api url."

```
Make sure you follow the below points:

* You can define your own custom connection with any name you want. But make sure to inherit the class CustomStrongTypeConnection.
> [!Note] Do not directly use the connection class CustomStrongTypeConnection.
* For connection api keys, please use the `Secret` type to mark that as a secret. Secret keys would be scrubbed so it can be more secure.
* You can either have your custom connection class with your custom tool, or in a seprate python file.
* Write comments of docstring for your custom strong type connection. Follow the format of docstring like this. Use `param` and `type` to explain each key.
```python
"""My custom strong type connection.
:param api_key: The api key get from "https://xxx.com".
:type api_key: String
:param api_base: The api base.
:type api_base: String
"""
```
The explaination of each connection would be parsed into connection template, so that when creating a custom strong type connection, it would be much understandable for user to know what each key means and thus what value to fill in.
```yaml
name: "to_replace_with_connection_name"
type: custom
custom_type: MyCustomConnection
module: my_tool_package.tools.my_tool_with_custom_strong_type_connection
package: test-custom-tools
package_version: 0.0.2
configs:
api_url: "This is a fake api url." # String, The api key get from "https://xxx.com".
secrets:
api_key: <user-input> # Don't replace the '<user-input>' placeholder. The application will prompt you to enter a value when it runs.
```
## Develop a flow with a package tool with custom strong type connection
* Step1: Refer to [create and use tool package](create-and-use-tool-package.md#create-custom-tool-package) to build and install your tool package in local environment.
> [!Note] After installing the new tool package in local environment, you will need to reload the window to make it in effect.
* Step2: Develop a flow with custom tools. Please take this [folder](../../../examples/flows/standard/flow-with-script-tool-with-custom-strong-type-connection/) as an example.
* Step3: Create a custom strong type connection.
There are three ways to create a connection:
- Click 'Add connection' button in node interface.
![create_custom_strong_type_connection_1](../../media/how-to-guides/develop-a-tool/create_custom_strong_type_connection_1.png)
- Click 'Create connection' add sign.
![create_custom_strong_type_connection_2](../../media/how-to-guides/develop-a-tool/create_custom_strong_type_connection_2.png)
- Click 'Create connection' add sign in custom catogory.
![create_custom_strong_type_connection_3](../../media/how-to-guides/develop-a-tool/create_custom_strong_type_connection_3.png)
Fill in the `values` starting with `to-replace-with` in the connection template.
![custom_strong_type_connection_template](../../media/how-to-guides/develop-a-tool/custom_strong_type_connection_template.png)

* Step4: Use the created custom strong type connection in your flow and run.
![use_custom_strong_type_connection_in_flow](../../media/how-to-guides/develop-a-tool/use_custom_strong_type_connection_in_flow.png)

## Develop a flow with a script tool with custom strong type connection
* Step1: Develop a flow with custom tools. Please take this [folder](../../../examples/flows/standard/flow-with-script-tool-with-custom-strong-type-connection/) as an example.
* Step2: Experience of using custom strong type connection in script tool is slightly different from using in package tool. When creating the connection, you will create a `CustomConnection`.
- Create a custom connection and fill in the `keys` and `values` in the connection template.
- Fill in the `keys` and `values` in connection template
* Step4: Use the created custom connection in your flow.
![use_custom_connection_in_flow](../../media/how-to-guides/develop-a-tool/use_custom_connection_in_flow.png)

## Local to cloud
Either you are using custom strong type connection in package tool or script tool, when creating necessary connections in Azure AI, you would need to create a `CustomConnection`. And in the node interface of the flow, the input type would also be shown as `CustomConnection` type.

For more details, please refer to this [doc](https://microsoft.github.io/promptflow/cloud/azureai/quick-start.html?highlight=pfazure) to run promptflow in Azure AI.

Example commands:
```
pfazure run create --subscription 96aede12-2f73-41cb-b983-6d11a904839b -g promptflow -w chjinche-pf-eus --flow D:\proj\github\ms\promptflow\examples\flows\standard\flow-with-package-tool-with-custom-strong-type-connection --data D:\proj\github\ms\promptflow\examples\flows\standard\flow-with-package-tool-with-custom-strong-type-connection\data.jsonl --runtime test-compute
```

```
pfazure run create --subscription 96aede12-2f73-41cb-b983-6d11a904839b -g promptflow -w chjinche-pf-eus --flow D:\proj\github\ms\promptflow\examples\flows\standard\flow-with-script-tool-with-custom-strong-type-connection --data D:\proj\github\ms\promptflow\examples\flows\standard\flow-with-script-tool-with-custom-strong-type-connection\data.jsonl --runtime test-compute
```
1 change: 1 addition & 0 deletions docs/how-to-guides/develop-a-tool/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ We provide guides on how to develop a tool and use it.
create-and-use-tool-package
add-a-tool-icon
use-file-path-as-tool-input
create-your-own-custom-strong-type-connection
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[WIP]
# Flow with additional_includes

User sometimes need to reference some common files or folders, this sample demos how to solve the problem using additional_includes. The file or folders in additional includes will be
copied to the snapshot folder by promptflow when operate this flow.

## Tools used in this flow
- LLM Tool
- Python Tool

## What you will learn

In this flow, you will learn
- how to add additional includes to the flow

## Prerequisites

Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```

## Getting Started

### 1. Add additional includes to flow

You can add this field `additional_includes` into the [`flow.dag.yaml`](flow.dag.yaml).
The value of this field is a list of the relative file/folder path to the flow folder.

``` yaml
additional_includes:
- ../web-classification/classify_with_llm.jinja2
- ../web-classification/convert_to_dict.py
- ../web-classification/fetch_text_content_from_url.py
- ../web-classification/prepare_examples.py
- ../web-classification/summarize_text_content.jinja2
- ../web-classification/summarize_text_content__variant_1.jinja2
```
### 2. Test & run the flow with additional includes
In this sample, this flow will references some files in the [web-classification](../web-classification/README.md) flow.
You can execute this flow with additional_include or submit it to cloud. The snapshot generated by Promptflow contains additional include files/folders.
#### Test flow with single line data
```bash
# test with default input value in flow.dag.yaml
pf flow test --flow .
# test with user specified inputs
pf flow test --flow . --inputs url='https://www.microsoft.com/en-us/d/xbox-wireless-controller-stellar-shift-special-edition/94fbjc7h0h6h'
```


#### Run with multi-line data

```bash
# create run using command line args
pf run create --flow . --data ./data.jsonl --stream
# create run using yaml file
pf run create --file run.yml --stream
```

#### Submit run to cloud

Assume we already have a connection named `open_ai_connection` in workspace.

```bash
# set default workspace
az account set -s <your_subscription_id>
az configure --defaults group=<your_resource_group_name> workspace=<your_workspace_name>
```

``` bash
# create run
pfazure run create --flow . --data ./data.jsonl --stream --runtime demo-mir
# pfazure run create --flow . --data ./data.jsonl --stream # automatic runtime
pfazure run create --file run.yml --runtime demo-mir
# pfazure run create --file run.yml --stream # automatic runtime
```

Note: Click portal_url of the run to view the final snapshot.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"text": "hello world!"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
inputs:
my_input:
type: string
default: hello
outputs:
my_output:
type: string
reference: ${my_package_tool.output}
nodes:
- name: my_package_tool
type: python
source:
type: package
tool: my_tool_package.tools.my_tool_2.MyTool.my_tool
inputs:
connection: my_second_connection
input_text: ${inputs.my_input}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[WIP]
# Flow with additional_includes

User sometimes need to reference some common files or folders, this sample demos how to solve the problem using additional_includes. The file or folders in additional includes will be
copied to the snapshot folder by promptflow when operate this flow.

## Tools used in this flow
- LLM Tool
- Python Tool

## What you will learn

In this flow, you will learn
- how to add additional includes to the flow

## Prerequisites

Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```

## Getting Started

### 1. Add additional includes to flow

You can add this field `additional_includes` into the [`flow.dag.yaml`](flow.dag.yaml).
The value of this field is a list of the relative file/folder path to the flow folder.

``` yaml
additional_includes:
- ../web-classification/classify_with_llm.jinja2
- ../web-classification/convert_to_dict.py
- ../web-classification/fetch_text_content_from_url.py
- ../web-classification/prepare_examples.py
- ../web-classification/summarize_text_content.jinja2
- ../web-classification/summarize_text_content__variant_1.jinja2
```
### 2. Test & run the flow with additional includes
In this sample, this flow will references some files in the [web-classification](../web-classification/README.md) flow.
You can execute this flow with additional_include or submit it to cloud. The snapshot generated by Promptflow contains additional include files/folders.
#### Test flow with single line data
```bash
# test with default input value in flow.dag.yaml
pf flow test --flow .
# test with user specified inputs
pf flow test --flow . --inputs url='https://www.microsoft.com/en-us/d/xbox-wireless-controller-stellar-shift-special-edition/94fbjc7h0h6h'
```


#### Run with multi-line data

```bash
# create run using command line args
pf run create --flow . --data ./data.jsonl --stream
# create run using yaml file
pf run create --file run.yml --stream
```

#### Submit run to cloud

Assume we already have a connection named `open_ai_connection` in workspace.

```bash
# set default workspace
az account set -s <your_subscription_id>
az configure --defaults group=<your_resource_group_name> workspace=<your_workspace_name>
```

``` bash
# create run
pfazure run create --flow . --data ./data.jsonl --stream --runtime demo-mir
# pfazure run create --flow . --data ./data.jsonl --stream # automatic runtime
pfazure run create --file run.yml --runtime demo-mir
# pfazure run create --file run.yml --stream # automatic runtime
```

Note: Click portal_url of the run to view the final snapshot.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"text": "hello world!"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
inputs:
my_input:
type: string
default: hello
outputs:
my_output:
type: string
reference: ${my_script_tool.output}
nodes:
- name: my_script_tool
type: python
source:
type: code
path: my_script_tool.py
inputs:
connection: custom_connection
input_param: ${inputs.my_input}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from promptflow import tool
from promptflow.connections import CustomStrongTypeConnection
from promptflow.contracts.types import Secret

import requests


class MyCustomConnection(CustomStrongTypeConnection):
"""My custom strong type connection.
:param api_key: The api key.
:type api_key: String
:param api_base: The api base.
:type api_base: String
"""
api_key: Secret
api_url: str = "This is a fake api url."


@tool
def my_tool(connection: MyCustomConnection, input_param: str) -> str:
# Replace with your tool code.
# Use custom strong type connection like: connection.api_key, connection.api_url
headers = {"api-key": str(connection.api_key)}
params = {
"input_text": input_param
}
try:
response = requests.get(connection.api_url, headers=headers, params=params)
if response.status_code == requests.codes.ok:
return response.json()
except Exception:
return ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from promptflow import tool
from promptflow.connections import CustomStrongTypeConnection
from promptflow.contracts.types import Secret

import requests


class MyCustomConnection(CustomStrongTypeConnection):
"""My custom strong type connection.
:param api_key: The api key.
:type api_key: String
:param api_base: The api base.
:type api_base: String
"""
api_key: Secret
api_url: str = "This is a fake api url."


@tool
def my_tool(connection: MyCustomConnection, input_param: str) -> str:
# Replace with your tool code.
# Use custom strong type connection like: connection.api_key, connection.api_url
headers = {"api-key": str(connection.api_key)}
params = {
"input_text": input_param
}
try:
response = requests.get(connection.api_url, headers=headers, params=params)
if response.status_code == requests.codes.ok:
return response.json()
except Exception:
return ""
Loading

0 comments on commit a979108

Please sign in to comment.