chore: import upstream snapshot with attribution
tools_continuous_delivery / Private PyPI non-main branch release (push) Has been skipped
tools_continuous_delivery / Private PyPI main branch release (push) Failing after 2m42s
Publish Promptflow Doc / Build (push) Has been cancelled
Publish Promptflow Doc / Deploy (push) Has been cancelled
Flake8 Lint / flake8 (push) Has been cancelled
Spell check CI / Spell_Check (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:52 +08:00
commit e768098d0e
4004 changed files with 2804145 additions and 0 deletions
@@ -0,0 +1 @@
include my_tool_package/yamls/*.yaml
@@ -0,0 +1 @@
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

@@ -0,0 +1 @@
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
@@ -0,0 +1,11 @@
from promptflow.core import tool
from promptflow.connections import CustomConnection
@tool
def my_tool(connection: CustomConnection, input_text: str) -> str:
# Replace with your tool code.
# Usually connection contains configs to connect to an API.
# Use CustomConnection is a dict. You can use it like: connection.api_key, connection.api_base
# Not all tools need a connection. You can remove it if you don't need it.
return "Hello " + input_text
@@ -0,0 +1,20 @@
from promptflow.core import ToolProvider, tool
from promptflow.connections import CustomConnection
class MyTool(ToolProvider):
"""
Doc reference :
"""
def __init__(self, connection: CustomConnection):
super().__init__()
self.connection = connection
@tool
def my_tool(self, input_text: str) -> str:
# Replace with your tool code.
# Usually connection contains configs to connect to an API.
# Use CustomConnection is a dict. You can use it like: connection.api_key, connection.api_base
# Not all tools need a connection. You can remove it if you don't need it.
return "Hello " + input_text
@@ -0,0 +1,27 @@
from enum import Enum
from promptflow.core import tool
class UserType(str, Enum):
STUDENT = "student"
TEACHER = "teacher"
@tool
def my_tool(user_type: Enum, student_id: str = "", teacher_id: str = "") -> str:
"""This is a dummy function to support cascading inputs.
:param user_type: user type, student or teacher.
:param student_id: student id.
:param teacher_id: teacher id.
:return: id of the user.
If user_type is student, return student_id.
If user_type is teacher, return teacher_id.
"""
if user_type == UserType.STUDENT:
return student_id
elif user_type == UserType.TEACHER:
return teacher_id
else:
raise Exception("Invalid user.")
@@ -0,0 +1,20 @@
from jinja2 import Template
from promptflow.core import tool
from promptflow.connections import CustomConnection
from promptflow.contracts.types import PromptTemplate
@tool
def my_tool(
connection: CustomConnection,
api: str,
deployment_name: str,
temperature: float,
prompt: PromptTemplate,
**kwargs
) -> str:
# Replace with your tool code, customise your own code to handle and use the prompt here.
# Usually connection contains configs to connect to an API.
# Not all tools need a connection. You can remove it if you don't need it.
rendered_prompt = Template(prompt, trim_blocks=True, keep_trailing_newline=True).render(**kwargs)
return rendered_prompt
@@ -0,0 +1,22 @@
from promptflow.core import tool
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 get from "https://xxx.com".
:type api_key: Secret
:param api_base: The api base.
:type api_base: String
"""
api_key: Secret
api_base: str = "This is a fake api base."
@tool
def my_tool(connection: MyCustomConnection, input_text: str) -> str:
# Replace with your tool code.
# Use custom strong type connection like: connection.api_key, connection.api_base
return "Hello " + input_text
@@ -0,0 +1,80 @@
from promptflow.core import tool
from typing import List, Union, Dict
def my_list_func(prefix: str = "", size: int = 10, **kwargs) -> List[Dict[str, Union[str, int, float, list, Dict]]]:
"""This is a dummy function to generate a list of items.
:param prefix: prefix to add to each item.
:param size: number of items to generate.
:param kwargs: other parameters.
:return: a list of items. Each item is a dict with the following keys:
- value: for backend use. Required.
- display_value: for UI display. Optional.
- hyperlink: external link. Optional.
- description: information icon tip. Optional.
"""
import random
words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon"]
result = []
for i in range(size):
random_word = f"{random.choice(words)}{i}"
cur_item = {
"value": random_word,
"display_value": f"{prefix}_{random_word}",
"hyperlink": f'https://www.bing.com/search?q={random_word}',
"description": f"this is {i} item",
}
result.append(cur_item)
return result
def list_endpoint_names(subscription_id: str = None,
resource_group_name: str = None,
workspace_name: str = None,
prefix: str = "") -> List[Dict[str, str]]:
"""This is an example to show how to get Azure ML resource in tool input list function.
:param subscription_id: Azure subscription id.
:param resource_group_name: Azure resource group name.
:param workspace_name: Azure ML workspace name.
:param prefix: prefix to add to each item.
"""
# return an empty list if workspace triad is not available.
if not subscription_id or not resource_group_name or not workspace_name:
return []
from azure.ai.ml import MLClient
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
credential.get_token("https://management.azure.com/.default")
ml_client = MLClient(
credential=credential,
subscription_id=subscription_id,
resource_group_name=resource_group_name,
workspace_name=workspace_name)
result = []
for ep in ml_client.online_endpoints.list():
hyperlink = (
f"https://ml.azure.com/endpoints/realtime/{ep.name}/detail?wsid=/subscriptions/"
f"{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft."
f"MachineLearningServices/workspaces/{workspace_name}"
)
cur_item = {
"value": ep.name,
"display_value": f"{prefix}_{ep.name}",
# external link to jump to the endpoint page.
"hyperlink": hyperlink,
"description": f"this is endpoint: {ep.name}",
}
result.append(cur_item)
return result
@tool
def my_tool(input_prefix: str, input_text: list, endpoint_name: str) -> str:
return f"Hello {input_prefix} {','.join(input_text)} {endpoint_name}"
@@ -0,0 +1,12 @@
import importlib
from pathlib import Path
from promptflow.core import tool
from promptflow.contracts.types import FilePath
@tool
def my_tool(input_file: FilePath, input_text: str) -> str:
# customise your own code to handle and use the input_file here
new_module = importlib.import_module(Path(input_file).stem)
return new_module.hello(input_text)
@@ -0,0 +1,125 @@
from typing import Union
from promptflow.core import tool
from typing import Dict, List
from promptflow.connections import AzureOpenAIConnection, OpenAIConnection, CognitiveSearchConnection
def generate_index_json(
index_type: str,
index: str = "",
index_connection: CognitiveSearchConnection = "",
index_name: str = "",
content_field: str = "",
embedding_field: str = "",
metadata_field: str = "",
semantic_configuration: str = "",
embedding_connection: Union[AzureOpenAIConnection, OpenAIConnection] = "",
embedding_deployment: str = ""
) -> str:
"""This is a dummy function to generate a index json based on the inputs.
"""
import json
inputs = ""
if index_type == "Azure Cognitive Search":
# 1. Call to create a new index
# 2. Call to get the index yaml and return as a json
inputs = {
"index_type": index_type,
"index": "retrieved_index",
"index_connection": index_connection,
"index_name": index_name,
"content_field": content_field,
"embedding_field": embedding_field,
"metadata_field": metadata_field,
"semantic_configuration": semantic_configuration,
"embedding_connection": embedding_connection,
"embedding_deployment": embedding_deployment
}
elif index_type == "Workspace MLIndex":
# Call to get the index yaml and return as a json
inputs = {
"index_type": index_type,
"index": index,
"index_connection": "retrieved_index_connection",
"index_name": "retrieved_index_name",
"content_field": "retrieved_content_field",
"embedding_field": "retrieved_embedding_field",
"metadata_field": "retrieved_metadata_field",
"semantic_configuration": "retrieved_semantic_configuration",
"embedding_connection": "retrieved_embedding_connection",
"embedding_deployment": "retrieved_embedding_deployment"
}
result = json.dumps(inputs)
return result
def reverse_generate_index_json(index_json: str) -> Dict:
"""This is a dummy function to generate origin inputs from index_json.
"""
import json
# Calculate the UI inputs based on the index_json
result = json.loads(index_json)
return result
def list_index_types(subscription_id, resource_group_name, workspace_name) -> List[str]:
return [
{"value": "Azure Cognitive Search"},
{"value": "PineCone"},
{"value": "FAISS"},
{"value": "Workspace MLIndex"},
{"value": "MLIndex from path"}
]
def list_indexes(
subscription_id,
resource_group_name,
workspace_name
) -> List[Dict[str, Union[str, int, float, list, Dict]]]:
import random
words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon"]
result = []
for i in range(10):
random_word = f"{random.choice(words)}{i}"
cur_item = {
"value": random_word,
"display_value": f"index_{random_word}",
"hyperlink": f'https://www.bing.com/search?q={random_word}',
"description": f"this is {i} item",
}
result.append(cur_item)
return result
def list_fields(subscription_id, resource_group_name, workspace_name) -> List[str]:
return [
{"value": "id"},
{"value": "content"},
{"value": "catelog"},
{"value": "sourcepage"},
{"value": "sourcefile"},
{"value": "title"},
{"value": "content_hash"},
{"value": "meta_json_string"},
{"value": "content_vector_open_ai"}
]
def list_semantic_configuration(subscription_id, resource_group_name, workspace_name) -> List[str]:
return [{"value": "azureml-default"}]
def list_embedding_deployment(embedding_connection: str) -> List[str]:
return [{"value": "text-embedding-ada-002"}, {"value": "ada-1k-tpm"}]
@tool
def my_tool(index_json: str, queries: str, top_k: int) -> str:
return f"Hello {index_json}"
@@ -0,0 +1,20 @@
from pathlib import Path
from ruamel.yaml import YAML
def collect_tools_from_directory(base_dir) -> dict:
tools = {}
yaml = YAML()
for f in Path(base_dir).glob("**/*.yaml"):
with open(f, "r") as f:
tools_in_file = yaml.load(f)
for identifier, tool in tools_in_file.items():
tools[identifier] = tool
return tools
def list_package_tools():
"""List package tools"""
yaml_dir = Path(__file__).parents[1] / "yamls"
return collect_tools_from_directory(yaml_dir)
@@ -0,0 +1,13 @@
my_tool_package.tools.my_tool_1.my_tool:
function: my_tool
inputs:
connection:
type:
- CustomConnection
input_text:
type:
- string
module: my_tool_package.tools.my_tool_1
name: My First Tool
description: This is my first tool
type: python
@@ -0,0 +1,14 @@
my_tool_package.tools.my_tool_2.MyTool.my_tool:
class_name: MyTool
function: my_tool
inputs:
connection:
type:
- CustomConnection
input_text:
type:
- string
module: my_tool_package.tools.my_tool_2
name: My Second Tool
description: This is my second tool
type: python
@@ -0,0 +1,23 @@
my_tool_package.tools.tool_with_cascading_inputs.my_tool:
function: my_tool
inputs:
user_type:
type:
- string
enum:
- student
- teacher
student_id:
type:
- string
enabled_by: user_type
enabled_by_value: [student]
teacher_id:
type:
- string
enabled_by: user_type
enabled_by_value: [teacher]
module: my_tool_package.tools.tool_with_cascading_inputs
name: My Tool with Cascading Inputs
description: This is my tool with cascading inputs
type: python
@@ -0,0 +1,27 @@
my_tool_package.tools.tool_with_custom_llm_type.my_tool:
name: My Custom LLM Tool
description: This is a tool to demonstrate how to customize an LLM tool with a PromptTemplate.
type: custom_llm
module: my_tool_package.tools.tool_with_custom_llm_type
function: my_tool
inputs:
connection:
type:
- CustomConnection
ui_hints:
text_box_size: lg
api:
type:
- string
ui_hints:
text_box_size: sm
deployment_name:
type:
- string
ui_hints:
text_box_size: md
temperature:
type:
- double
ui_hints:
text_box_size: xs
@@ -0,0 +1,15 @@
my_tool_package.tools.tool_with_custom_strong_type_connection.my_tool:
description: This is my tool with custom strong type connection.
function: my_tool
inputs:
connection:
custom_type:
- MyCustomConnection
type:
- CustomConnection
input_text:
type:
- string
module: my_tool_package.tools.tool_with_custom_strong_type_connection
name: Tool With Custom Strong Type Connection
type: python
@@ -0,0 +1,46 @@
my_tool_package.tools.tool_with_dynamic_list_input.my_tool:
function: my_tool
inputs:
input_prefix:
type:
- string
input_text:
type:
- list
dynamic_list:
func_path: my_tool_package.tools.tool_with_dynamic_list_input.my_list_func
func_kwargs:
- name: prefix # argument name to be passed to the function
type:
- string
# if optional is not specified, default to false.
# this is for UX pre-validaton. If optional is false, but no input. UX can throw error in advanced.
optional: true
reference: ${inputs.input_prefix} # dynamic reference to another input parameter
- name: size # another argument name to be passed to the function
type:
- int
optional: true
default: 10
# enum and dynamic list may need below setting.
# allow user to enter input value manually, default false.
allow_manual_entry: true
# allow user to select multiple values, default false.
is_multi_select: true
endpoint_name:
type:
- string
dynamic_list:
func_path: my_tool_package.tools.tool_with_dynamic_list_input.list_endpoint_names
func_kwargs:
- name: prefix
type:
- string
optional: true
reference: ${inputs.input_prefix}
allow_manual_entry: false
is_multi_select: false
module: my_tool_package.tools.tool_with_dynamic_list_input
name: My Tool with Dynamic List Input
description: This is my tool with dynamic list input
type: python
@@ -0,0 +1,13 @@
my_tool_package.tools.tool_with_file_path_input.my_tool:
function: my_tool
inputs:
input_file:
type:
- file_path
input_text:
type:
- string
module: my_tool_package.tools.tool_with_file_path_input
name: Tool with FilePath Input
description: This is a tool to demonstrate the usage of FilePath input
type: python
@@ -0,0 +1,142 @@
my_tool_package.tools.tool_with_generated_by_input.my_tool:
function: my_tool
inputs:
index_json:
type:
- string
generated_by:
func_path: my_tool_package.tools.tool_with_generated_by_input.generate_index_json
func_kwargs:
- name: index_type
type:
- string
reference: ${inputs.index_type}
- name: index
type:
- string
optional: true
reference: ${inputs.index}
- name: index_connection
type: [CognitiveSearchConnection]
optional: true
reference: ${inputs.index_connection}
- name: index_name
type:
- string
optional: true
reference: ${inputs.index_name}
- name: content_field
type:
- string
optional: true
reference: ${inputs.content_field}
- name: embedding_field
type:
- string
optional: true
reference: ${inputs.embedding_field}
- name: metadata_field
type:
- string
optional: true
reference: ${inputs.metadata_field}
- name: semantic_configuration
type:
- string
optional: true
reference: ${inputs.semantic_configuration}
- name: embedding_connection
type: [AzureOpenAIConnection, OpenAIConnection]
optional: true
reference: ${inputs.embedding_connection}
- name: embedding_deployment
type:
- string
optional: true
reference: ${inputs.embedding_deployment}
reverse_func_path: my_tool_package.tools.tool_with_generated_by_input.reverse_generate_index_json
queries:
type:
- string
top_k:
type:
- int
index_type:
type:
- string
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_index_types
input_type: uionly_hidden
index:
type:
- string
enabled_by: index_type
enabled_by_value: ["Workspace MLIndex"]
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_indexes
input_type: uionly_hidden
index_connection:
type: [CognitiveSearchConnection]
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
input_type: uionly_hidden
index_name:
type:
- string
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
input_type: uionly_hidden
content_field:
type:
- string
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_fields
input_type: uionly_hidden
embedding_field:
type:
- string
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_fields
input_type: uionly_hidden
metadata_field:
type:
- string
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_fields
input_type: uionly_hidden
semantic_configuration:
type:
- string
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_semantic_configuration
input_type: uionly_hidden
embedding_connection:
type: [AzureOpenAIConnection, OpenAIConnection]
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
input_type: uionly_hidden
embedding_deployment:
type:
- string
enabled_by: index_type
enabled_by_value: ["Azure Cognitive Search"]
dynamic_list:
func_path: my_tool_package.tools.tool_with_generated_by_input.list_embedding_deployment
func_kwargs:
- name: embedding_connection
type:
- string
reference: ${inputs.embedding_connection}
input_type: uionly_hidden
module: my_tool_package.tools.tool_with_generated_by_input
name: Tool with Generated By Input
description: This is a tool with generated by input
type: python
@@ -0,0 +1,19 @@
from setuptools import find_packages, setup
PACKAGE_NAME = "my-tools-package"
setup(
name=PACKAGE_NAME,
version="0.0.13",
description="This is my tools package",
packages=find_packages(),
entry_points={
"package_tools": ["my_tools = my_tool_package.tools.utils:list_package_tools"],
},
include_package_data=True, # This line tells setuptools to include files from MANIFEST.in
extras_require={
"azure": [
"azure-ai-ml>=1.11.0,<2.0.0"
]
},
)
@@ -0,0 +1,28 @@
import pytest
import unittest
from promptflow.connections import CustomConnection
from my_tool_package.tools.my_tool_1 import my_tool
@pytest.fixture
def my_custom_connection() -> CustomConnection:
my_custom_connection = CustomConnection(
{
"api-key" : "my-api-key",
"api-secret" : "my-api-secret",
"api-url" : "my-api-url"
}
)
return my_custom_connection
class TestMyTool1:
def test_my_tool_1(self, my_custom_connection):
result = my_tool(my_custom_connection, input_text="Microsoft")
assert result == "Hello Microsoft"
# Run the unit tests
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,34 @@
import pytest
import unittest
from promptflow.connections import CustomConnection
from my_tool_package.tools.my_tool_2 import MyTool
@pytest.fixture
def my_custom_connection() -> CustomConnection:
my_custom_connection = CustomConnection(
{
"api-key" : "my-api-key",
"api-secret" : "my-api-secret",
"api-url" : "my-api-url"
}
)
return my_custom_connection
@pytest.fixture
def my_tool_provider(my_custom_connection) -> MyTool:
my_tool_provider = MyTool(my_custom_connection)
return my_tool_provider
class TestMyTool2:
def test_my_tool_2(self, my_tool_provider: MyTool):
result = my_tool_provider.my_tool(input_text="Microsoft")
assert result == "Hello Microsoft"
# Run the unit tests
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,6 @@
from my_tool_package.tools.tool_with_cascading_inputs import my_tool
def test_my_tool():
result = my_tool(user_type="student", student_id="student_id")
assert result == '123'
@@ -0,0 +1,34 @@
import pytest
import unittest
from promptflow.connections import CustomConnection
from my_tool_package.tools.tool_with_custom_llm_type import my_tool
@pytest.fixture
def my_custom_connection() -> CustomConnection:
my_custom_connection = CustomConnection(
{
"api-key" : "my-api-key",
"api-secret" : "my-api-secret",
"api-url" : "my-api-url"
}
)
return my_custom_connection
class TestToolWithCustomLLMType:
def test_tool_with_custom_llm_type(self, my_custom_connection):
result = my_tool(
my_custom_connection,
"my-api",
"my-deployment-name",
0,
"Hello {{text}}",
text="Microsoft")
assert result == "Hello Microsoft"
# Run the unit tests
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,26 @@
import pytest
import unittest
from my_tool_package.tools.tool_with_custom_strong_type_connection import MyCustomConnection, my_tool
@pytest.fixture
def my_custom_connection() -> MyCustomConnection:
my_custom_connection = MyCustomConnection(
{
"api_key" : "my-api-key",
"api_base" : "my-api-base"
}
)
return my_custom_connection
class TestMyToolWithCustomStrongTypeConnection:
def test_my_tool(self, my_custom_connection):
result = my_tool(my_custom_connection, input_text="Microsoft")
assert result == "Hello Microsoft"
# Run the unit tests
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,12 @@
from my_tool_package.tools.tool_with_dynamic_list_input import my_tool, my_list_func
def test_my_tool():
result = my_tool(input_text=["apple", "banana"], input_prefix="My")
assert result == 'Hello My apple,banana'
def test_my_list_func():
result = my_list_func(prefix="My")
assert len(result) == 10
assert "value" in result[0]
@@ -0,0 +1,22 @@
import pytest
import unittest
from promptflow.contracts.types import FilePath
from my_tool_package.tools.tool_with_file_path_input import my_tool
@pytest.fixture
def my_file_path_input() -> FilePath:
my_file_path_input = FilePath("tests.test_utils.hello_method.py")
return my_file_path_input
class TestToolWithFilePathInput:
def test_tool_with_file_path_input(self, my_file_path_input):
result = my_tool(my_file_path_input, input_text="Microsoft")
assert result == "Hello Microsoft"
# Run the unit tests
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,89 @@
import json
import pytest
import unittest
from my_tool_package.tools.tool_with_generated_by_input import (
generate_index_json,
list_embedding_deployment,
list_fields,
list_indexes,
list_index_types,
list_semantic_configuration,
my_tool,
reverse_generate_index_json,
)
@pytest.mark.parametrize("index_type", ["Azure Cognitive Search", "Workspace MLIndex"])
def test_my_tool(index_type):
index_json = generate_index_json(index_type=index_type)
result = my_tool(index_json, "", "")
assert result == f'Hello {index_json}'
def test_generate_index_json():
index_type = "Azure Cognitive Search"
index_json = generate_index_json(index_type=index_type)
indexes = json.loads(index_json)
assert indexes["index_type"] == index_type
def test_reverse_generate_index_json():
index_type = "Workspace MLIndex"
index = list_indexes("", "", "")
inputs = {
"index_type": index_type,
"index": index,
"index_connection": "retrieved_index_connection",
"index_name": "retrieved_index_name",
"content_field": "retrieved_content_field",
"embedding_field": "retrieved_embedding_field",
"metadata_field": "retrieved_metadata_field",
"semantic_configuration": "retrieved_semantic_configuration",
"embedding_connection": "retrieved_embedding_connection",
"embedding_deployment": "retrieved_embedding_deployment"
}
input_json = json.dumps(inputs)
result = reverse_generate_index_json(input_json)
for k, v in inputs.items():
assert result[k] == v
def test_list_index_types():
result = list_index_types("", "", "")
assert isinstance(result, list)
assert len(result) == 5
def test_list_indexes():
result = list_indexes("", "", "")
assert isinstance(result, list)
assert len(result) == 10
for item in result:
assert isinstance(item, dict)
def test_list_fields():
result = list_fields("", "", "")
assert isinstance(result, list)
assert len(result) == 9
for item in result:
assert isinstance(item, dict)
def test_list_semantic_configuration():
result = list_semantic_configuration("", "", "")
assert len(result) == 1
assert isinstance(result[0], dict)
def test_list_embedding_deployment():
result = list_embedding_deployment("")
assert len(result) == 2
for item in result:
assert isinstance(item, dict)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,3 @@
def hello(input_text: str) -> str:
# Replace with your own code.
return "Hello " + input_text
@@ -0,0 +1,23 @@
# Basic flow with package tool using cascading inputs
This is a flow demonstrating the use of a tool with cascading inputs which frequently used in situations where the selection in one input field determines what subsequent inputs should be shown,
and it helps in creating a more efficient, user-friendly, and error-free input process.
Tools used in this flow
- `python` Tool
Connections used in this flow:
- None
## Prerequisites
Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```
## Run flow
- Test flow
```bash
pf flow test --flow .
```
@@ -0,0 +1,17 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
environment:
python_requirements_txt: requirements.txt
inputs: {}
outputs:
user_id:
type: string
reference: ${Tool_with_Cascading_Inputs.output}
nodes:
- name: Tool_with_Cascading_Inputs
type: python
source:
type: package
tool: my_tool_package.tools.tool_with_cascading_inputs.my_tool
inputs:
user_type: student
student_id: "student_id"
@@ -0,0 +1,2 @@
promptflow
my-tools-package==0.0.7
@@ -0,0 +1,72 @@
# Basic flow with package tool using custom strong type connection
This is a flow demonstrating the use of a package tool with custom string type connection which provides a secure way to manage credentials for external APIs and data sources, and it offers an improved user-friendly and intellisense experience compared to custom connections.
Tools used in this flow
- custom package tool
Connections used in this flow:
- custom strong type connection
## Prerequisites
Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```
## Setup connection
Create connection if you haven't done that.
```bash
# Override keys with --set to avoid yaml file changes
pf connection create -f my_custom_connection.yml --set secrets.api_key='<your_api_key>' configs.api_base='<your_api_base>'
```
Ensure you have created `my_custom_connection` connection.
```bash
pf connection show -n my_custom_connection
```
## Run flow
### Run with single line input
```bash
# test with default input value in flow.dag.yaml
pf flow test --flow .
# test with flow inputs
pf flow test --flow . --inputs text="Promptflow"
```
### Run with multiple lines data
- create run
```bash
pf run create --flow . --data ./data.jsonl --stream
```
- list and show run meta
```bash
# list created run
pf run list -r 3
# get a sample run name
name=$(pf run list -r 10 | jq '.[] | select(.name | contains("custom_strong_type")) | .name'| head -n 1 | tr -d '"')
# show specific run detail
pf run show --name $name
# show output
pf run show-details --name $name
# visualize run in browser
pf run visualize --name $name
```
### Run with connection override
Run flow with newly created connection.
```bash
pf run create --flow . --data ./data.jsonl --connections my_package_tool.connection=my_custom_connection --stream
```
@@ -0,0 +1,3 @@
{"text": "Python Hello World!"}
{"text": "C Hello World!"}
{"text": "C# Hello World!"}
@@ -0,0 +1,18 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs:
text:
type: string
default: Microsoft
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.tool_with_custom_strong_type_connection.my_tool
inputs:
connection: my_custom_connection
input_text: ${inputs.text}
@@ -0,0 +1,11 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/CustomStrongTypeConnection.schema.json
name: "my_custom_connection"
type: custom
custom_type: MyCustomConnection
module: my_tool_package.tools.tool_with_custom_strong_type_connection
package: my-tools-package
package_version: 0.0.5
configs:
api_base: "This is a fake api base." # String type. The api base.
secrets: # must-have
api_key: "to_replace_with_api_key" # Secret type. The api key get from "https://xxx.com".
@@ -0,0 +1,2 @@
promptflow[azure]
my-tools-package==0.0.5
@@ -0,0 +1,72 @@
# Basic flow with script tool using custom strong type connection
This is a flow demonstrating the use of a script tool with custom string type connection which provides a secure way to manage credentials for external APIs and data sources, and it offers an improved user-friendly and intellisense experience compared to custom connections.
Tools used in this flow
- custom `python` tool
Connections used in this flow:
- custom strong type connection
## Prerequisites
Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```
## Setup connection
Create connection if you haven't done that.
```bash
# Override keys with --set to avoid yaml file changes
pf connection create -f custom.yml --set secrets.api_key='<your_api_key>' configs.api_base='<your_api_base>'
```
Ensure you have created `normal_custom_connection` connection.
```bash
pf connection show -n normal_custom_connection
```
## Run flow
### Run with single line input
```bash
# test with default input value in flow.dag.yaml
pf flow test --flow .
# test with flow inputs
pf flow test --flow . --inputs text="Promptflow"
```
### Run with multiple lines data
- create run
```bash
pf run create --flow . --data ./data.jsonl --stream
```
- list and show run meta
```bash
# list created run
pf run list -r 3
# get a sample run name
name=$(pf run list -r 10 | jq '.[] | select(.name | contains("custom_strong_type")) | .name'| head -n 1 | tr -d '"')
# show specific run detail
pf run show --name $name
# show output
pf run show-details --name $name
# visualize run in browser
pf run visualize --name $name
```
### Run with connection override
Run flow with newly created connection.
```bash
pf run create --flow . --data ./data.jsonl --connections my_script_tool.connection=normal_custom_connection --stream
```
@@ -0,0 +1,7 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/CustomConnection.schema.json
name: normal_custom_connection
type: custom
configs:
api_base: test
secrets: # must-have
api_key: <to-be-replaced>
@@ -0,0 +1,3 @@
{"text": "Python Hello World!"}
{"text": "C Hello World!"}
{"text": "C# Hello World!"}
@@ -0,0 +1,18 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs:
text:
type: string
default: Microsoft
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: normal_custom_connection
input_text: ${inputs.text}
@@ -0,0 +1,22 @@
from promptflow.core import tool
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: Secret
:param api_base: The api base.
:type api_base: String
"""
api_key: Secret
api_base: str = "This is a fake api base."
@tool
def my_tool(connection: MyCustomConnection, input_text: str) -> str:
# Replace with your tool code.
# Use custom strong type connection like: connection.api_key, connection.api_base
return "Hello " + input_text
@@ -0,0 +1,34 @@
# Flow with custom_llm tool
This is a flow demonstrating how to use a `custom_llm` tool, which enables users to seamlessly connect to a large language model with prompt tuning experience using a `PromptTemplate`.
Tools used in this flow:
- `custom_llm` Tool
Connections used in this flow:
- custom connection
## Prerequisites
Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```
## Setup connection
Create connection if you haven't done that.
```bash
# Override keys with --set to avoid yaml file changes
pf connection create -f custom_connection.yml --set secrets.api_key=<your_api_key> configs.api_base=<your_api_base>
```
Ensure you have created `basic_custom_connection` connection.
```bash
pf connection show -n basic_custom_connection
```
## Run flow
- Test flow
```bash
pf flow test --flow .
```
@@ -0,0 +1,7 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/CustomConnection.schema.json
name: basic_custom_connection
type: custom
configs:
api_base: <to-be-replaced>
secrets: # must-have
api_key: <to-be-replaced>
@@ -0,0 +1,26 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs:
website_name:
type: string
default: Microsoft
user_name:
type: string
default: ""
outputs:
output:
type: string
reference: ${my_custom_llm_tool.output}
nodes:
- name: my_custom_llm_tool
type: custom_llm
source:
type: package_with_prompt
tool: my_tool_package.tools.tool_with_custom_llm_type.my_tool
path: prompt_template.jinja2
inputs:
connection: basic_custom_connection
api: ''
website_name: ${inputs.website_name}
user_name: ${inputs.user_name}
deployment_name: ''
temperature: 1
@@ -0,0 +1,6 @@
Welcome to {{ website_name }}!
{% if user_name %}
Hello, {{ user_name }}!
{% else %}
Hello there!
{% endif %}
@@ -0,0 +1,2 @@
promptflow
my-tools-package
@@ -0,0 +1,22 @@
# Basic flow with tool using a dynamic list input
This is a flow demonstrating how to use a tool with a dynamic list input.
Tools used in this flow:
- `python` Tool
Connections used in this flow:
- None
## Prerequisites
Install promptflow sdk and other dependencies:
```bash
pip install -r requirements.txt
```
## Run flow
- Test flow
```bash
pf flow test --flow .
```
@@ -0,0 +1,18 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs: {}
outputs:
output:
type: string
reference: ${My_Tool_with_Dynamic_List_Input_cywc.output}
nodes:
- name: My_Tool_with_Dynamic_List_Input_cywc
type: python
source:
type: package
tool: my_tool_package.tools.tool_with_dynamic_list_input.my_tool
inputs:
input_prefix: hi
input_text:
- grape3
- elderberry5
endpoint_name: my_endpoint
@@ -0,0 +1,2 @@
promptflow
my-tools-package
@@ -0,0 +1,18 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs:
input:
type: string
default: Microsoft
outputs:
output:
type: string
reference: ${Tool_with_FilePath_Input.output}
nodes:
- name: Tool_with_FilePath_Input
type: python
source:
type: package
tool: my_tool_package.tools.tool_with_file_path_input.my_tool
inputs:
input_text: ${inputs.input}
input_file: hello_method.py
@@ -0,0 +1,3 @@
def hello(input_text: str) -> str:
# Replace with your own code.
return "Hello " + input_text
@@ -0,0 +1,3 @@
promptflow
promptflow-tools
my-tools-package