promptflow Documentation

Build high-quality LLM apps - from prototyping, testing to production deployment and monitoring.

RAW Doc

Technical Documentation: microsoft/promptflow

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (README.md)

Prompt flow

[!WARNING]
Prompt flow in Microsoft Foundry and Azure Machine Learning will be retired on April 20, 2027. Prompt flow is no longer recommended for new development. Migrate existing Prompt flow applications and deployments to Microsoft Agent Framework before April 20, 2027.

Prompt flow container images are no longer receiving updates, including security and package updates. This applies to Prompt flow runtime images, including promptflow-runtime, promptflow-runtime-stable, and promptflow-python.

After April 20, 2027, Prompt flow, including the web authoring experience in Microsoft Foundry and Azure Machine Learning, the VS Code extensions, and related Prompt flow container images, will no longer be supported or available.

If your application depends on Prompt flow deployments or runtime images, plan to move those workloads to supported alternatives such as Microsoft Agent Framework before the retirement date. For migration guidance, see the Prompt flow migration guide and migration code samples.









Welcome to join us to make prompt flow better by
participating discussions,
opening issues,
submitting PRs.

Prompt flow is a suite of development tools designed to streamline the end-to-end development cycle of LLM-based AI applications, from ideation, prototyping, testing, evaluation to production deployment and monitoring. It makes prompt engineering much easier and enables you to build LLM apps with production quality.

With prompt flow, you will be able to:

  • Create and iteratively develop flow
  • Evaluate flow quality and performance
    • Evaluate your flow's quality and performance with larger datasets.
    • Integrate the testing and evaluation into your CI/CD system to ensure quality of your flow.
  • Streamlined development cycle for production
    • Deploy your flow to the serving platform you choose or integrate into your app's code base easily.
    • (Optional but highly recommended) Collaborate with your team by leveraging the cloud version of Prompt flow in Azure AI.

Installation

To get started quickly, you can use a pre-built development environment. Click the button below to open the repo in GitHub Codespaces, and then continue the readme!

If you want to get started in your local environment, first install the packages:

Ensure you have a python environment, python>=3.9, <=3.11 is recommended.

sh
pip install promptflow promptflow-tools

Quick Start ⚑

Create a chatbot with prompt flow

Run the command to initiate a prompt flow from a chat template, it creates folder named my_chatbot and generates required files within it:

sh
pf flow init --flow ./my_chatbot --type chat

Setup a connection for your API key

For OpenAI key, establish a connection by running the command, using the openai.yaml file in the my_chatbot folder, which stores your OpenAI key (override keys and name with --set to avoid yaml file changes):

sh
pf connection create --file ./my_chatbot/openai.yaml --set api_key=<your_api_key> --name open_ai_connection

For Azure OpenAI key, establish the connection by running the command, using the azure_openai.yaml file:

sh
pf connection create --file ./my_chatbot/azure_openai.yaml --set api_key=<your_api_key> api_base=<your_api_base> --name open_ai_connection

Chat with your flow

In the my_chatbot folder, there's a flow.dag.yaml file that outlines the flow, including inputs/outputs, nodes, connection, and the LLM model, etc

Note that in the chat node, we're using a connection named open_ai_connection (specified in connection field) and the gpt-35-turbo model (specified in deployment_name field). The deployment_name filed is to specify the OpenAI model, or the Azure OpenAI deployment resource.

Interact with your chatbot by running: (press Ctrl + C to end the session)

sh
pf flow test --flow ./my_chatbot --interactive

Core value: ensuring "High Quality” from prototype to production

Explore our 15-minute tutorial that guides you through prompt tuning ➑ batch testing ➑ evaluation, all designed to ensure high quality ready for production.

Next Step! Continue with the Tutorial πŸ‘‡ section to delve deeper into prompt flow.

Tutorial πŸƒβ€β™‚οΈ

Prompt flow is a tool designed to build high quality LLM apps, the development process in prompt flow follows these steps: develop a flow, improve the flow quality, deploy the flow to production.

Develop your own LLM apps

VS Code Extension

We also offer a VS Code extension (a flow designer) for an interactive flow development experience with UI.

You can install it from the visualstudio marketplace.

Deep delve into flow development

Getting started with prompt flow: A step by step guidance to invoke your first flow run.

Learn from use cases

Tutorial: Chat with PDF: An end-to-end tutorial on how to build a high quality chat application with prompt flow, including flow development and evaluation with metrics.

More examples can be found here. We welcome contributions of new use cases!

Setup for contributors

If you're interested in contributing, please start with our dev setup guide: dev_setup.md.

Next Step! Continue with the Contributing πŸ‘‡ section to contribute to prompt flow.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct.
For more information see the Code of Conduct FAQ or
contact [email protected] with any additional questions or comments.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
Microsoft's Trademark & Brand Guidelines.
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.

Code of Conduct

This project has adopted the
Microsoft Open Source Code of Conduct.
For more information see the
Code of Conduct FAQ
or contact [email protected]
with any additional questions or comments.

Data Collection

The software may collect information about you and your use of the software and
send it to Microsoft if configured to enable telemetry.
Microsoft may use this information to provide services and improve our products and services.
You may turn on the telemetry as described in the repository.
There are also some features in the software that may enable you and Microsoft
to collect data from users of your applications. If you use these features, you
must comply with applicable law, including providing appropriate notices to
users of your applications together with a copy of Microsoft's privacy
statement. Our privacy statement is located at
https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data
collection and use in the help documentation and our privacy statement. Your
use of the software operates as your consent to these practices.

Telemetry Configuration

Telemetry collection is on by default.

To opt out, please run pf config set telemetry.enabled=false to turn it off.

License

Copyright (c) Microsoft Corporation. All rights reserved.

Licensed under the MIT license.


README (`docs/README.md`)

Promptflow documentation contribute guidelines

This folder contains the source code for prompt flow documentation site.

This readme file will not be included in above doc site. It keeps a guide for promptflow documentation contributors.

Content

Below is a table of important doc pages.

Category Article
Quick start Getting started with prompt flow
Concepts Flows Tools Connections Variants
How-to guides How to initialize and test a flow How to run and evaluate a flow How to tune prompts using variantsHow to deploy a flowHow to create and use your own tool package
Tools reference LLM tool Prompt tool Python tool Embedding toolSERP API tool

Writing tips

  1. Reach the doc source repository by clicking Edit this page on any page.

  2. Please use :::{admonition} for experimental feature or notes, and admonition with dropdown for the Limitation Part.

  3. Please use ::::{tab-set} to group your sdk/cli example, and put the cli at first. Use :sync: to sync multiple tables .

  4. If you are unclear with the above lines, refer to get started to see the usage.

  5. Add gif: Use ScreenToGif to record your screen, edit and save as a gif.

  6. Reach more element style at Sphinx Design Components.

Preview your changes

Local build: We suggest using local build at the beginning, as it's fast and efficiency.

Please refer to How to build doc site locally.

FAQ

Adding image in doc

Please use markdown syntax `` to reference image, because the relative path of image will be changed after sphinx build, and image placed in html tags can not be referenced when build.

Draw flow chart in doc

We recommend using the mermaid, learn more from the mermaid syntax doc

Reference


Index (`docs/index.md`)


myst:
html_meta:
"description lang=en": "Prompt flow Doc"
"google-site-verification": "rEZN-2h5TVqEco07aaMpqNcDx4bjr2czx1Hwfoxydrg"

html_theme.sidebar_secondary.remove: true

:::{admonition} Prompt Flow Retirement Notice
:class: warning
Prompt Flow feature development ended on April 20, 2026. The feature will be fully retired on April 20, 2027. On the retirement date, Prompt Flow enters read-only mode. Your existing flows will continue to operate until that date.

Recommended action: Migrate your Prompt Flow workloads to Microsoft Agent Framework before April 20, 2027.
:::

Prompt flow

Prompt flow is a suite of development tools designed to streamline the end-to-end development cycle of LLM-based AI applications, from ideation, prototyping, testing, evaluation to production deployment and monitoring. It makes prompt engineering much easier and enables you to build LLM apps with production quality.

With prompt flow, you will be able to:

  • Create flows that link LLMs, prompts, Python code and other tools together in a executable workflow.
  • Debug and iterate your flows, especially tracing interaction with LLMs with ease.
  • Evaluate your flows, calculate quality and performance metrics with larger datasets.
  • Integrate the testing and evaluation into your CI/CD system to ensure quality of your flow.
  • Deploy your flows to the serving platform you choose or integrate into your app's code base easily.
  • (Optional but highly recommended) Collaborate with your team by leveraging the cloud version of Prompt flow in Azure AI.

Welcome to join us to make prompt flow better by
participating discussions,
opening issues,
submitting PRs.

This documentation site contains guides for prompt flow sdk, cli and vscode extension users.

{gallery-grid}
:grid-columns: 1 2 2 2
- header: "πŸš€ Quick Start"
  content: "
    Quick start and end-to-end tutorials.<br/><br/>
    - [Getting started with prompt flow](how-to-guides/quick-start.md)<br/>
    - [E2E development tutorial: chat with PDF](https://github.com/microsoft/promptflow/blob/main/examples/tutorials/e2e-development/chat-with-pdf.md)<br/>
    - Find more: [tutorials & samples](tutorials/index.md)<br/>
  "

- header: "πŸ“’ How-to Guides"
  content: "
    Articles guide user to complete a specific task in prompt flow.<br/><br/>
    - [Tracing](how-to-guides/tracing/index.md)<br/>
    - [Develop a flow](how-to-guides/develop-a-flex-flow/index.md)<br/>
    - [Run and evaluate a flow](how-to-guides/run-and-evaluate-a-flow/index.md)<br/>
    - [Deploy a flow](how-to-guides/deploy-a-flow/index.md)<br/>
  "
{gallery-grid}
:grid-columns: 1 2 2 2
- header: "πŸ“‘ Concepts"
  content: "
    Introduction of key concepts of prompt flow.<br/><br/>
    - [Flows](concepts/concept-flows.md)<br/>
    - [Tools](concepts/concept-tools.md)<br/>
    - [Connections](concepts/concept-connections.md)<br/>
    - [Design principles](concepts/design-principles.md)<br/>
  "


- header: "πŸ” Reference"
  content: "
    Reference provides technical information about prompt flow API.<br/><br/>
    - Command line Interface reference: [pf](reference/pf-command-reference.md)<br/>
    - Python library reference: [promptflow](reference/python-library-reference/promptflow-core/promptflow.rst)<br/>
    - Tool reference: [LLM Tool](reference/tools-reference/llm-tool.md), [Python Tool](reference/tools-reference/python-tool.md), [Prompt Tool](reference/tools-reference/prompt-tool.md)<br/>
    - ChangeLog: [ChangeLog](reference/changelog/promptflow.md)<br/>
  "
{toctree}
:hidden:
:maxdepth: 1
how-to-guides/index
{toctree}
:hidden:
:maxdepth: 1
tutorials/index
{toctree}
:hidden:
:maxdepth: 2
concepts/index
{toctree}
:hidden:
:maxdepth: 1
reference/index
{toctree}
:hidden:
:maxdepth: 1
cloud/index
{toctree}
:hidden:
:maxdepth: 1
integrations/index

Cloud Index (`docs/cloud/index.md`)

Cloud

Prompt flow streamlines the process of developing AI applications based on LLM, easing prompt engineering, prototyping, evaluating, and fine-tuning for high-quality products.

Transitioning to production, however, typically requires a comprehensive LLMOps process, LLMOps is short for large language model operations. This can often be a complex task, demanding high availability and security, particularly vital for large-scale team collaboration and lifecycle management when deploying to production.

To assist in this journey, we've introduced Azure AI, a cloud-based platform tailored for executing LLMOps, focusing on boosting productivity for enterprises.

  • Private data access and controls
  • Collaborative development
  • Automating iterative experimentation and CI/CD
  • Deployment and optimization
  • Safe and Responsible AI

Transitioning from local to cloud (Azure AI)

In prompt flow, You can develop your flow locally and then seamlessly transition to Azure AI. Here are a few scenarios where this might be beneficial:

Scenario Benefit How to
Collaborative development Azure AI provides a cloud-based platform for flow development and management, facilitating sharing and collaboration across multiple teams, organizations, and tenants. Submit a run using pfazure, based on the flow file in your code base.
Processing large amounts of data in parallel pipelines Transitioning to Azure AI allows you to use your flow as a parallel component in a pipeline job, enabling you to process large amounts of data and integrate with existing pipelines. Learn how to Use flow in Azure ML pipeline job.
Large-scale Deployment Azure AI allows for seamless deployment and optimization when your flow is ready for production and requires high availability and security. Use pf flow build to deploy your flow to Azure App Service.
Data Security and Responsible AI Practices If your flow handling sensitive data or requiring ethical AI practices, Azure AI offers robust security, responsible AI services, and features for data storage, identity, and access control. Follow the steps mentioned in the above scenarios.

For more resources on Azure AI, visit the cloud documentation site: Build AI solutions with prompt flow.

{toctree}
:caption: Flow
:maxdepth: 2
azureai/manage-flows
azureai/run-promptflow-in-azure-ai
azureai/create-run-with-compute-session
azureai/use-flow-in-azure-ml-pipeline
azureai/generate-test-data-cloud.md
{toctree}
:caption: Deployment
:maxdepth: 2
azureai/deploy-to-azure-appservice
{toctree}
:caption: FAQ
:maxdepth: 2
azureai/faq
azureai/consume-connections-from-azure-ai
azureai/runtime-change-log.md

Concepts Index (`docs/concepts/index.md`)

Concepts

In this section, you will learn the basic concepts of prompt flow.

{toctree}
:maxdepth: 1

concept-flows
concept-tools
concept-connections
concept-variants
design-principles

How To Guides Index (`docs/how-to-guides/index.md`)

How-to Guides

Simple and short articles grouped by topics, each introduces a core feature of prompt flow and how you can use it to address your specific use cases.

{toctree}
:caption: Quick start
:maxdepth: 1
quick-start
installation/index
{toctree}
:caption: Tracing
:maxdepth: 1
tracing/index
{toctree}
:caption: Prompty
:maxdepth: 1
develop-a-prompty/index
{toctree}
:caption: Flow
:maxdepth: 1
develop-a-flex-flow/index
develop-a-dag-flow/index
execute-flow-as-a-function
chat-with-a-flow/index
run-and-evaluate-a-flow/index
{toctree}
:caption: Tool
:maxdepth: 1
develop-a-tool/index
{toctree}
:caption: Deployment
:maxdepth: 1
deploy-a-flow/index
enable-streaming-mode
{toctree}
:caption: FAQ
:maxdepth: 1
faq
set-promptflow-configs
manage-connections
tune-prompts-with-variants

Integrations Index (`docs/integrations/index.md`)

Integrations

The Integrations section contains documentation on custom extensions created by the community that expand prompt flow's capabilities.
These include tools that enrich flows, as well as tutorials on innovative ways to use prompt flow.

{toctree}
:maxdepth: 1

tools/index
llms/index

Reference Index (`docs/reference/index.md`)

Reference

Current stable version:

{toctree}
:caption: Command Line Interface
:maxdepth: 1

pf-command-reference.md
pfazure-command-reference.md
{toctree}
:caption: Python Library ChangeLog
:maxdepth: 1

changelog/promptflow
{toctree}
:caption: Python Library Reference
:maxdepth: 1

python-library-reference/promptflow-tracing/promptflow
python-library-reference/promptflow-core/promptflow
python-library-reference/promptflow-devkit/promptflow
python-library-reference/promptflow-azure/promptflow
python-library-reference/promptflow-rag/promptflow
python-library-reference/promptflow-evals/promptflow
{toctree}
:caption: Tool Reference
:maxdepth: 1

tools-reference/llm-tool
tools-reference/llm-vision-tool
tools-reference/prompt-tool
tools-reference/python-tool
tools-reference/serp-api-tool
tools-reference/faiss_index_lookup_tool
tools-reference/vector_db_lookup_tool
tools-reference/embedding_tool
tools-reference/open_model_llm_tool
tools-reference/openai-gpt-4v-tool
tools-reference/contentsafety_text_tool
tools-reference/aoai-gpt4-turbo-vision
tools-reference/rerank-tool
{toctree}
:caption: YAML Schema
:maxdepth: 1

flow-yaml-schema-reference.md
run-yaml-schema-reference.md
{toctree}
:caption: Trace Specification
:maxdepth: 1

trace-span-spec-reference.md

Tutorials Index (`docs/tutorials/index.md`)

Tutorials

This section contains a collection of flow samples and step-by-step tutorials.

Category Sample Description
Tracing Tracing Prompt flow provides the tracing feature to capture and visualize the internal execution details for all flows
Tracing Tracing with llm application Tracing LLM application
Tracing Tracing with autogen Tracing LLM calls in autogen group chat application
Tracing Tracing with langchain apps Tracing LLM calls in langchain application
Tracing Tracing with custom opentelemetry collector A tutorial on how to levarage custom OTLP collector.
Prompty Getting started with prompty A quickstart tutorial to run a prompty and evaluate it.
Prompty Chat with prompty A quickstart tutorial to run a chat prompty and evaluate it.
Prompty Prompty output format
Flow Getting started with flex flow A quickstart tutorial to run a flex flow and evaluate it.
Flow Chat with class based flex flow A quickstart tutorial to run a class based flex flow and evaluate it.
Flow Stream chat with async flex flow A quickstart tutorial to run a class based flex flow in stream mode and evaluate it.
Flow Stream chat with flex flow A quickstart tutorial to run a class based flex flow in stream mode and evaluate it.
Flow Getting started with dag flow A quickstart tutorial to run a flow and evaluate it.
Flow Execute flow as a function This guide will walk you through the main scenarios of executing flow as a function.
Flow Run flows in azure ml pipeline Create pipeline using components to run a distributed job with tensorflow
Flow Flow run management in azure Flow run management in Azure AI
Flow Flow run management Flow run management
Flow Evaluate with langchain's evaluator A tutorial to converting LangChain criteria evaluator application to flex flow.
Flow Getting started with flex flow in azure A quickstart tutorial to run a flex flow and evaluate it in Azure.
Flow Chat with class based flex flow in azure A quickstart tutorial to run a class based flex flow and evaluate it in azure.
Flow Run dag flow in azure A quickstart tutorial to run a flow in Azure AI and evaluate it.
Deployment Create service with flow This example shows how to create a simple service with flow
Deployment Deploy a flow using docker This example demos how to deploy flow as a docker app
Deployment Distribute flow as executable app This example demos how to package flow as a executable app
Deployment Deploy flow using azure app service This example demos how to deploy a flow using Azure App Service
Deployment Deploy flow using kubernetes This example demos how to deploy flow as a Kubernetes app
Rag Tutorial: chat with pdf Retrieval Augmented Generation (or RAG) has become a prevalent pattern to build intelligent application with Large Language Models (or LLMs) since it can infuse external knowledge into the model, which is not trained with those up-to-date or proprietary information
Rag Tutorial: how prompt flow helps on quality improvement This tutorial is designed to enhance your understanding of improving flow quality through prompt tuning and evaluation
Rag Chat with pdf - test, evaluation and experimentation A tutorial of chat-with-pdf flow that allows user ask questions about the content of a PDF file and get answers
Rag Develop copilot with promptflow In this tutorial, we will provide a detailed walkthrough on creating a RAG-based copilot using the Azure Machine Learning promptflow toolkit
Rag How to generate test data based on documents In this doc, you will learn how to generate test data based on your documents for RAG app
Rag Chat with pdf in azure A tutorial of chat-with-pdf flow that executes in Azure AI

Learn more: Try out more promptflow examples.


How To Guides Chat With A Flow Index (`docs/how-to-guides/chat-with-a-flow/index.md`)

Chat with a flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Prompt flow provides the chat window feature to facilitate an interactive chat experience within a local environment.
You can engage in conversation with the flow and view its responses directly within the chat window.

Initiating a chat window

There are two methods to open a chat window: executing the prompt flow CLI command or clicking the
Open test chat page button when viewing a flow YAML file in the Prompt flow VS Code extension.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

The following CLI command allows you to trigger a chat window.

shell
pf flow test --flow . --ui

Running the above command will yield the following example output:

text
Starting prompt flow service...
...
You can begin chat flow on http://127.0.0.1:**/v1.0/ui/chat?flow=***

The browser page corresponding to the chat URL will automatically open and direct the user to a chat page
corresponding to the passed flow:

:::

:::{tab-item} VS Code Extension
:sync: VSC

Click the Open test chat page button while viewing a flow YAML file in the Prompt flow VS Code extension, and you
will be directed to the chat page.

:::
::::


How To Guides Deploy A Flow Index (`docs/how-to-guides/deploy-a-flow/index.md`)

Deploy a flow

A flow can be deployed to multiple platforms, such as a local development service, Docker container, Kubernetes cluster, etc.

{gallery-grid}
:grid-columns: 1 2 2 3
- image: ../../media/how-to-guides/local.png
  content: "<center><b>Development server</b></center>"
  website: deploy-using-dev-server.html

- image: ../../media/how-to-guides/docker.png
  content: "<center><b>Docker</b></center>"
  website: deploy-using-docker.html
  
- image: ../../media/how-to-guides/kubernetes.png
  content: "<center><b>Kubernetes</b></center>"
  website: deploy-using-kubernetes.html

We also provide guides to deploy to cloud, such as azure app service:

{gallery-grid}
:grid-columns: 1 2 2 3

- image: ../../media/how-to-guides/appservice.png
  content: "<center><b>Azure App Service</b></center>"
  website: ../../cloud/azureai/deploy-to-azure-appservice.html

We are working on more official deployment guides for other hosting providers, and welcome user submitted guides.

{toctree}
:maxdepth: 1
:hidden:

deploy-using-dev-server
deploy-using-docker
deploy-using-kubernetes
distribute-flow-as-executable-app

How To Guides Develop A Dag Flow Index (`docs/how-to-guides/develop-a-dag-flow/index.md`)

Develop a dag flow

LLM apps can be defined as Directed Acyclic Graphs (DAGs) of function calls. These DAGs are flows in prompt flow.

A DAG flow in prompt flow is a DAG of functions (we call them tools). These functions/tools connected via input/output dependencies and executed based on the topology by prompt flow executor.

A flow is represented as a YAML file and can be visualized with our Prompt flow for VS Code extension. Here is an example flow.dag.yaml:

Please refer to our examples and guides in this section to learn how to write a DAG flow.

Note:

  • promptflow also support user develop a a flow using code. learn more on comparasion of these two flow concepts.
{toctree}
:maxdepth: 1

quick-start
init-and-test-a-flow
develop-standard-flow
develop-chat-flow
develop-evaluation-flow
add-conditional-control-to-a-flow
process-image-in-flow
referencing-external-files-or-folders-in-a-flow

How To Guides Develop A Flex Flow Index (`docs/how-to-guides/develop-a-flex-flow/index.md`)

Develop a flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

You can create LLM apps using a Python function or class as the entry point, which encapsulating your app logic. You can directly test or run these entries with pure code experience.

In PromptFlow, these functions or classes are referred to as flow or flex flow.

Alternatively, you can define a flow.flex.yaml that points to these entries (entry:function_name or entry:ClassName). This enables testing, running, or viewing traces via the Promptflow VS Code Extension.

Our examples should give you a good idea on how to write flows.

Note:

  • The term Flex is a shorthand for flexible, indicating its adaptability to most scenarios with minimal adjustments.
  • PromptFlow also supports the development of a dag flow. learn more on comparasion of these two flow concepts.
{toctree}
:maxdepth: 1

function-based-flow
class-based-flow
input-output-format
model-config
connection-support

How To Guides Develop A Prompty Index (`docs/how-to-guides/develop-a-prompty/index.md`)

Develop a prompty

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Promptflow introduces the prompty feature, it is designed to simplify the development of prompt templates for customers.

Create a prompty

Prompty specification

In promptflow, file bearing the .prompty extension is recognized as a prompty. This unique file type facilitates the development of prompt template.

Prompty is a markdown file, this front matter, structured in YAML, encapsulates a series of metadata fields pivotal for defining the model’s configuration and the inputs for the prompty.
After this front matter is the prompt template, articulated in the Jinja format.

Fields in the front matter:

Field Description
name The name of the prompt.
description A description of the prompt.
model Details the prompty's model configuration, including connection info and parameters for the LLM request.
inputs The input definition that passed to prompt template.
outputs Specify the fields in prompty result. (Only works when response_format is json_object).
sample Offers a dictionary or JSON file containing sample data for inputs.
yaml
---
name: Basic Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    azure_deployment: gpt-35-turbo
    connection: azure_open_ai_connection
  parameters:
    max_tokens: 128
    temperature: 0.2
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: Who is the most famous person in the world?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly,
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
{{question}}

Load a prompty

prompty are designed with flexibility in mind, allowing users to override the default model configuration during the loading process.

::::{tab-set}
:::{tab-item} Azure OpenAI
:sync: Azure OpenAI

yaml
---
name: Basic Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    azure_deployment: gpt-35-turbo
    api_key: ${env:AZURE_OPENAI_API_KEY}
    api_version: ${env:AZURE_OPENAI_API_VERSION}
    azure_endpoint: ${env:AZURE_OPENAI_ENDPOINT}
  parameters:
    max_tokens: 128
    temperature: 0.2
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: Who is the most famous person in the world?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly,
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
{{question}}

Users can specify alternative parameters or utilize environment variables to adjust the model settings. The format ${env:ENV_NAME} is used to reference environment variables.

  • Using a dictionary

    python
    from promptflow.core import Prompty
    
    # Load prompty with dict override
    override_model = {
        "configuration": {
            "api_key": "${env:AZURE_OPENAI_API_KEY}",
            "api_version": "${env:AZURE_OPENAI_API_VERSION}",
            "azure_endpoint": "${env:AZURE_OPENAI_ENDPOINT}"
        },
        "parameters": {"max_tokens": 512}
    }
    prompty = Prompty.load(source="path/to/prompty.prompty", model=override_model)
  • Using AzureOpenAIModelConfiguration:

    python
    from promptflow.core import Prompty, AzureOpenAIModelConfiguration
    
    # Load prompty with AzureOpenAIModelConfiguration override
    configuration = AzureOpenAIModelConfiguration(
        azure_deployment="gpt-3.5-turbo",
        api_key="${env:AZURE_OPENAI_API_KEY}",
        api_version="${env:AZURE_OPENAI_API_VERSION}",
        azure_endpoint="${env:AZURE_OPENAI_ENDPOINT}"
    )
    override_model = {
        "configuration": configuration,
        "parameters": {"max_tokens": 512}
    }
    prompty = Prompty.load(source="path/to/prompty.prompty", model=override_model)

:::

:::{tab-item} OpenAI
:sync: OpenAI

yaml
---
name: Basic Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: openai
    model: gpt-3.5-turbo
    api_key: ${env:OPENAI_API_KEY}
    base_url: ${env:OPENAI_BASE_URL}
  parameters:
    max_tokens: 128
    temperature: 0.2
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: Who is the most famous person in the world?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly,
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
  {{question}}

Users can specify alternative parameters or utilize environment variables to adjust the model settings. The format ${env:ENV_NAME} is used to reference environment variables.

  • Using a dictionary

    python
    from promptflow.core import Prompty
    
    # Load prompty with dict override
    override_model = {
        "configuration": {
            "api_key": "${env:OPENAI_API_KEY}",
            "base_url": "${env:OPENAI_BASE_URL}",
        },
        "parameters": {"max_tokens": 512}
    }
    prompty = Prompty.load(source="path/to/prompty.prompty", model=override_model)
  • Using OpenAIModelConfiguration

    python
    from promptflow.core import Prompty, OpenAIModelConfiguration
    
    # Load prompty with OpenAIModelConfiguration override
    configuration = OpenAIModelConfiguration(
        model="gpt-35-turbo",
        base_url="${env:OPENAI_BASE_URL}",
        api_key="${env:OPENAI_API_KEY}",
    )
    override_model = {
        "configuration": configuration,
        "parameters": {"max_tokens": 512}
    }
    prompty = Prompty.load(source="path/to/prompty.prompty", model=override_model)

:::
::::

Execute a prompty

Promptflow offers versatile methods for executing a prompty to meet the needs of customers in different scenarios.

Direct function call

Once loaded, the Prompty object can be invoked directly as a function, returning the content of the first choice in the LLM response.

python
from promptflow.core import Prompty

prompty_obj = Prompty.load(source="path/to/prompty.prompty")
result = prompty_obj(first_name="John", last_name="Doh", question="What is the capital of France?")

Testing prompty

Flow test

Execute and test your Prompty with inputs or a sample file.
::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
# Test prompty with default inputs
pf flow test --flow path/to/prompty.prompty

# Test prompty with specified inputs
pf flow test --flow path/to/prompty.prompty --inputs first_name=John last_name=Doh question="What is the capital of France?"

# Test prompty with sample file
pf flow test --flow path/to/prompty.prompty --inputs path/to/sample.json

A trace link will be provided in the terminal to visualize the internal execution details for this command.
For Prompty, users can find the generated prompt, LLM request parameters, and other information in the trace UI. Learn more.

:::

:::{tab-item} SDK
:sync: SDK

python
from promptflow.client import PFClient

pf = PFClient()

# Test prompty with specified inputs
result = pf.test(flow="path/to/prompty.prompty", inputs={"first_name": "John", "last_name": "Doh", "question": "What is the capital of France?"})

# Test prompty with sample file
result = pf.test(flow="path/to/prompty.prompty", inputs="path/to/sample.json")

:::
::::

Test with interactive mode

Promptflow CLI also provides an interactive chat session for testing chat flows.

bash
pf flow test --flow path/to/prompty.prompty --interactive
text
---
name: Basic Prompt With Chat History
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_open_ai
    azure_deployment: gpt-35-turbo
    connection: azure_open_ai_connection

  parameters:
    max_tokens: 128
    temperature: 0.2
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
   chat_history:
    type: list
sample:
  first_name: John
  last_name: Doe
  question: Who is the most famous person in the world?
  chat_history: [ { "role": "user", "content": "what's the capital of France?" }, { "role": "assistant", "content": "Paris" } ]
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly,
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

Here is a chat history you had with the user:
{% for item in chat_history %}
   {{item.role}}: {{item.content}}
{% endfor %}

user:
  {{question}}

Terminal outputs:

Batch run prompty

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

To execute a batch run of a Prompty in Promptflow, you can use the following commands:

bash
pf run create --flow path/to/prompty.prompty --data path/to/inputs.jsonl

:::

:::{tab-item} SDK
:sync: SDK

To execute a batch run of a Prompty in Promptflow, you can use the following SDK:

python
from promptflow.client import PFClient

pf = PFClient() 
# create run
prompty_run = pf.run(
    flow="path/to/prompty.prompty",
    data="path/to/inputs.jsonl",
)
pf.stream(prompty_run)

:::
::::

When executing a batch run, Promptflow provides a trace UI to visualize the internal execution details of the run. This feature allows you to track the execution details of each line in the data file, including the prompt and LLM request parameters. Learn more.

For example, after starting the Prompt flow service, you might see output like this in your terminal:

text
Prompt flow service has started...
You can view the traces from local: http://127.0.0.1:49240/v1.0/ui/traces/?#run=prompty_variant_0_20240424_152808_282517
[2024-04-24 15:28:12,597][promptflow._sdk._orchestrator.run_submitter][INFO] - Submitting run prompty_variant_0_20240424_152808_282517, log path: .promptflow\.runs\prompty_variant_0_20240424_152808_282517\logs.txt

The trace UI will record the execution details of each line in the data file, providing a comprehensive view of the batch run’s performance and outcomes.

{toctree}
:maxdepth: 1
:hidden:

prompty-output-format
use-prompty-in-flow

How To Guides Develop A Tool Index (`docs/how-to-guides/develop-a-tool/index.md`)

Develop a tool

We provide guides on how to develop a tool and use it.

{toctree}
:maxdepth: 1
:hidden:

create-and-use-tool-package
add-a-tool-icon
add-category-and-tags-for-tool
use-file-path-as-tool-input
customize_an_llm_tool
create-cascading-tool-inputs
create-your-own-custom-strong-type-connection
create-dynamic-list-tool-input

How To Guides Installation Index (`docs/how-to-guides/installation/index.md`)

Installation

The prompt flow SDK and CLI are under active development, with regular stable releases on PyPI:

. Refer to SDK Changelog for release history and upcoming features.

This guide outlines the Promptflow SDK and CLI installation process.

Create a virtual environment (optional)

When installing prompt flow locally, we recommend using a virtual environment for the installation. This ensures
that the dependencies for prompt flow are isolated from the rest of your system. Please ensure you have a working
python environment (python>=3.9,<4.0), a new virtual environment is preferred.

::::{tab-set}
:::{tab-item} venv
:sync: venv

To create and activate:

shell
python3 -m venv pf
source pf/bin/activate

To deactivate later, run:

shell
deactivate

:::

:::{tab-item} Conda
:sync: Conda
Install Conda if you have not already.
To create and activate:

shell
conda create -n pf python=3.11
conda activate pf

To deactivate later, run:

shell
conda deactivate

:::

::::

Install prompt flow

Run below command to install the latest version of the promptflow.

shell
# Install the latest stable version
pip install promptflow --upgrade

After developing your flow locally, you can seamlessly transition to Azure AI and interact with your flow in the cloud.
Use the following command to install the latest version of prompt flow to work with flows in Azure.

shell
# Install the latest stable version
pip install promptflow[azure] --upgrade

Promptflow sub packages

Prompt flow consists of several sub-packages, each is designed to provide specific functionalities.

Name Description
promptflow-tracing The promptflow-tracing package offers tracing capabilities to capture and illustrate the internal execution processes of both DAG flow and Flex flow.
promptflow-core The promptflow-core package provides the essential features needed to execute a flow in prompt flow.
promptflow-devkit The promptflow-devkit package offers features like: create and iteratively develop flow, evaluate flow quality and performance, and a streamlined development cycle for production.
promptflow-azure The promptflow-azure package helps user to leverage the cloud version of prompt flow in Azure AI

Verify installation

To verify the installation, run the following command to check the version of prompt flow installed.

shell
pf --version

Running the above command will yield the following example output:

text
{
  "promptflow": "1.10.1",
  "promptflow-core": "1.10.1",
  "promptflow-devkit": "1.10.1",
  "promptflow-tracing": "1.10.1"
}
{toctree}
:maxdepth: 1
:hidden:

standalone

How To Guides Run And Evaluate A Flow Index (`docs/how-to-guides/run-and-evaluate-a-flow/index.md`)

Run and evaluate a flow

After you have developed and tested the flow in init and test a flow, this guide will help you learn how to run a flow with a larger dataset and then evaluate the flow you have created.

Create a batch run

Since you have run your flow successfully with a small set of data, you might want to test if it performs well in large set of data, you can run a batch test and check the outputs.

A bulk test allows you to run your flow with a large dataset and generate outputs for each data row, and the run results will be recorded in local db so you can use pf commands to view the run results at anytime. (e.g. pf run list)

Let's create a run with flow web-classification. It is a flow demonstrating multi-class classification with LLM. Given an url, it will classify the url into one web category with just a few shots, simple summarization and classification prompts.

To begin with the guide, you need:

  • Git clone the sample repository(above flow link) and set the working directory to /examples/flows/.
  • Make sure you have already created the necessary connection.
    ::::{tab-set}

:::{tab-item} CLI
:sync: CLI

Create the run with flow and data, can add --stream to stream the run.

sh
pf run create --flow standard/web-classification --data standard/web-classification/data.jsonl --column-mapping url='${data.url}' --stream

Note column-mapping is a mapping from flow input name to specified values, see more details in Use column mapping.

You can also name the run by specifying --name my_first_run in above command, otherwise the run name will be generated in a certain pattern which has timestamp inside.

With a run name, you can easily view or visualize the run details using below commands:

sh
pf run show-details -n my_first_run
sh
pf run visualize -n my_first_run

More details can be found with pf run --help

:::
:::{tab-item} SDK
:sync: SDK

python
from promptflow.client import PFClient

# Please protect the entry point by using `if __name__ == '__main__':`,
# otherwise it would cause unintended side effect when promptflow spawn worker processes.
# Ref: https://docs.python.org/3/library/multiprocessing.html#the-spawn-and-forkserver-start-methods
if __name__ == "__main__":
  # PFClient can help manage your runs and connections.
  pf = PFClient()

  # Set flow path and run input data
  flow = "standard/web-classification" # set the flow directory
  data= "standard/web-classification/data.jsonl" # set the data file

  # create a run, stream it until it's finished
  base_run = pf.run(
      flow=flow,
      data=data,
      stream=True,
      # map the url field from the data to the url input of the flow
      column_mapping={"url": "${data.url}"},
  )
python
# get the inputs/outputs details of a finished run.
details = pf.get_details(base_run)
details.head(10)
python
# visualize the run in a web browser
pf.visualize(base_run)

Feel free to check Promptflow Python Library Reference for all SDK public interfaces.

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
Use the code lens action on the top of the yaml editor to trigger batch run

Click the bulk test button on the top of the visual editor to trigger flow test.

:::

::::

We also have a more detailed documentation Manage runs demonstrating how to manage your finished runs with CLI, SDK and VS Code Extension.

Evaluate your flow

You can use an evaluation method to evaluate your flow. The evaluation methods are also flows which use Python or LLM etc., to calculate metrics like accuracy, relevance score. Please refer to Develop evaluation flow to learn how to develop an evaluation flow.

In this guide, we use eval-classification-accuracy flow to evaluate. This is a flow illustrating how to evaluate the performance of a classification system. It involves comparing each prediction to the groundtruth and assigns a Correct or Incorrect grade, and aggregating the results to produce metrics such as accuracy, which reflects how good the system is at classifying the data.

Run evaluation flow against run

::::{tab-set}

:::{tab-item} CLI
:sync: CLI

Evaluate the finished flow run

After the run is finished, you can evaluate the run with below command, compared with the normal run create command, note there are two extra arguments:

  • column-mapping: A mapping from flow input name to specified data values. Reference here for detailed information.
  • run: The run name of the flow run to be evaluated.

More details can be found in Use column mapping.

sh
pf run create --flow evaluation/eval-classification-accuracy --data standard/web-classification/data.jsonl --column-mapping groundtruth='${data.answer}' prediction='${run.outputs.category}' --run my_first_run --stream

Same as the previous run, you can specify the evaluation run name with --name my_first_eval_run in above command.

You can also stream or view the run details with:

sh
pf run stream -n my_first_eval_run  # same as "--stream" in command "run create"
pf run show-details -n my_first_eval_run
pf run show-metrics -n my_first_eval_run

Since now you have two different runs my_first_run and my_first_eval_run, you can visualize the two runs at the same time with below command.

sh
pf run visualize -n "my_first_run,my_first_eval_run"

A web browser will be opened to show the visualization result.

:::

:::{tab-item} SDK
:sync: SDK

Evaluate the finished flow run

After the run is finished, you can evaluate the run with below command, compared with the normal run create command, note there are two extra arguments:

  • column-mapping: A dictionary represents sources of the input data that are needed for the evaluation method. The sources can be from the flow run output or from your test dataset.
    • If the data column is in your test dataset, then it is specified as ${data.<column_name>}.
    • If the data column is from your flow output, then it is specified as ${run.outputs.<output_name>}.
  • run: The run name or run instance of the flow run to be evaluated.

More details can be found in Use column mapping.

python
from promptflow.client import PFClient

# PFClient can help manage your runs and connections.
pf = PFClient()

# set eval flow path
eval_flow = "evaluation/eval-classification-accuracy"
data= "standard/web-classification/data.jsonl"

# run the flow with existing run
eval_run = pf.run(
    flow=eval_flow,
    data=data,
    run=base_run,
    column_mapping={  # map the url field from the data to the url input of the flow
      "groundtruth": "${data.answer}",
      "prediction": "${run.outputs.category}",
    }
)

# stream the run until it's finished
pf.stream(eval_run)

# get the inputs/outputs details of a finished run.
details = pf.get_details(eval_run)
details.head(10)

# view the metrics of the eval run
metrics = pf.get_metrics(eval_run)
print(json.dumps(metrics, indent=4))

# visualize both the base run and the eval run
pf.visualize([base_run, eval_run])

A web browser will be opened to show the visualization result.

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

There are actions to trigger local batch runs. To perform an evaluation you can use the run against "existing runs" actions.

:::

::::

Next steps

Learn more about:

{toctree}
:maxdepth: 1
:hidden:

use-column-mapping
manage-runs

How To Guides Tracing Index (`docs/how-to-guides/tracing/index.md`)

Tracing

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Traces records specific events or the state of an application during execution. It can include data about function calls, variable values, system events and more. Traces help break down an application's components into discrete inputs and outputs, which is crucial for debugging and understanding an application. You can learn more from here on traces.

Prompt flow provides the trace feature to enable user to trace LLM call or function, and LLM frameworks like LangChain and AutoGen, following OpenTelemetry specification.

Installing the package

bash
pip install promptflow-tracing

Instrumenting user's code

Enable trace for LLM calls

Let's start with the simplest example, add single line code start_trace() to enable trace for LLM calls in your application.

python
from openai import OpenAI
from promptflow.tracing import start_trace

# instrument OpenAI
start_trace()

client = OpenAI()

completion = client.chat.completions.create(
  model="gpt-4",
  messages=[
    {"role": "system", "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."},
    {"role": "user", "content": "Compose a poem that explains the concept of recursion in programming."}
  ]
)

print(completion.choices[0].message)

Then OpenAI is instrumented, and as prompt flow follows OpenTelemetry specification, user can fully leverage the OpenTelemetry knowledge to use these traces during the OpenAI calls.

Trace on any function

A more common scenario is the application has complicated code structure, and developer would like to add trace on critical path that they would like to debug and monitor.

See the math_to_code example on how to use @trace.

Execute below command will get an URL to display the trace records and trace details of each test.

python
from promptflow.tracing import trace

# trace your function
@trace
def code_gen(client: AzureOpenAI, question: str) -> str:
    sys_prompt = (
        "I want you to act as a Math expert specializing in Algebra, Geometry, and Calculus. "
        "Given the question, develop python code to model the user's question. "
        "Make sure only reply the executable code, no other words."
    )
    completion = client.chat.completions.create(
        model=os.getenv("CHAT_DEPLOYMENT_NAME", "gpt-35-turbo"),
        messages=[
            {
                "role": "system",
                "content": sys_prompt,
            },
            {"role": "user", "content": question},
        ],
    )
    raw_code = completion.choices[0].message.content
    result = code_refine(raw_code)
    return result
shell
python math_to_code.py

Trace LLM and frameworks

Prompt flow tracing works not only for general LLM application, but also for more frameworks like autogen and langchain. Besides basic tracing capability, prompt flow also provides several trace toolkits that can improve the tracing experience (e.g., trace UI for visualization).

  1. Example: Add trace for LLM

  2. Example: Add trace for Autogen

  3. Example: Add trace for Langchain

{toctree}
:maxdepth: 1
:hidden:

trace-ui
manage

Integrations Llms Index (`docs/integrations/llms/index.md`)

Alternative LLMs

This section provides tutorials on incorporating alternative large language models into prompt flow.

{toctree}
:maxdepth: 1
:hidden:

Integrations Tools Index (`docs/integrations/tools/index.md`)

Custom Tools

This section contains documentation for custom tools created by the community to extend Prompt flow's capabilities for specific use cases. These tools are developed following the guide on Creating and Using Tool Packages. They are not officially maintained or endorsed by the Prompt flow team. For questions or issues when using a tool, please use the support contact link in the table below.

Tool Package Index

The table below provides an index of custom tool packages. The columns contain:

  • Package Name: The name of the tool package. Links to the package documentation.
  • Description: A short summary of what the tool package does.
  • Owner: The creator/maintainer of the tool package.
  • Support Contact: Link to contact for support and reporting new issues.
Package Name Description Owner Support Contact
promptflow-azure-ai-language Collection of Azure AI Language Prompt flow tools. Sean Murray [email protected]
llmlingua-promptflow Speed up large language model's inference and enhance large language model's perceive of key information, compress the prompt with minimal performance loss. LLMLingua Team [email protected]
{toctree}
:maxdepth: 1
:hidden:

azure-ai-language-tool
llmlingua-prompt-compression-tool

Concepts Concept Connections (`docs/concepts/concept-connections.md`)

In prompt flow, you can utilize connections to securely manage credentials or secrets for external services.

Connections

Connections are for storing information about how to access external services like LLMs: endpoint, api keys etc.

  • In your local development environment, the connections are persisted in your local machine with keys encrypted.
  • In Azure AI, connections can be configured to be shared across the entire workspace. Secrets associated with connections are securely persisted in the corresponding Azure Key Vault, adhering to robust security and compliance standards.

Prompt flow provides a variety of pre-built connections, including Azure OpenAI, OpenAI, etc. These pre-built connections enable seamless integration with these resources within the built-in tools. Additionally, you have the flexibility to create custom connection types using key-value pairs, empowering them to tailor the connections to their specific requirements, particularly in Python tools.

Connection type Built-in tools
Azure OpenAI LLM or Python
OpenAI LLM or Python
Cognitive Search Vector DB Lookup or Python
Serp Serp API or Python
Serverless LLM or Python
Custom Python

By leveraging connections in prompt flow, you can easily establish and manage connections to external APIs and data sources, facilitating efficient data exchange and interaction within their AI applications.

Next steps


Concepts Concept Flows (`docs/concepts/concept-flows.md`)

While how LLMs work may be elusive to many developers, how LLM apps work is not - they essentially involve a series of calls to external services such as LLMs/databases/search engines, or intermediate data processing, all glued together.

Flows

Flex flow

You can create LLM apps using a Python function or class as the entry point, which encapsulating your app logic. You can directly test or run these with pure code experience. Or you can define a flow.flex.yaml that points to these entries, which enables testing, running, or viewing traces via the Promptflow VS Code Extension.

Our examples should also give you an idea how to write flex flows.

DAG flow

Thus LLM apps can be defined as Directed Acyclic Graphs (DAGs) of function calls. These DAGs are flows in prompt flow.

A DAG flow in prompt flow is a DAG of functions (we call them tools). These functions/tools connected via input/output dependencies and executed based on the topology by prompt flow executor.

A flow is represented as a YAML file and can be visualized with our Prompt flow for VS Code extension. Here is an example flow.dag.yaml:

Please refer to our examples to learn how to write a DAG flow.

When to use Flex or DAG flow

Dag flow provides a UI-friendly way to develop your LLM app, which has the following benefits:

  • Low code: user can drag-and-drop in UI to create a LLM app.
  • DAG Visualization: user can easily understand the logic structure of the app with DAG view.

Flex flow provides a code-friendly way to develop your LLM app, which has the following benefits:

  • Quick start: Users can quickly test with a simple prompt, then customize with python code with Tracing visualization UI.
  • More advanced orchestration: Users can write complex flow with Python built-in control operators (if-else, foreach) or other 3rd party / open-source library.
  • Easy onboard from other platforms: user might already onboard platforms like langchain and sematic kernel with existing code. User can easily onboard promptflow with a few code changes.

Flow types

Prompt flow examples organize flows by three categories:

  • Standard flow or Chat flow: these two are for you to develop your LLM application. The primary difference between the two lies in the additional support provided by the "Chat Flow" for chat applications. For instance, you can define chat_history, chat_input, and chat_output for your flow. The prompt flow, in turn, will offer a chat-like experience (including conversation history) during the development of the flow. Moreover, it also provides a sample chat application for deployment purposes.
  • Evaluation flow is for you to test/evaluate the quality of your LLM application (standard/chat flow). It usually run on the outputs of standard/chat flow, and compute some metrics that can be used to determine whether the standard/chat flow performs well. E.g. is the answer accurate? is the answer fact-based?

Flex flow examples:

  • basic: A basic standard flow define using function entry that calls Azure OpenAI with connection info stored in environment variables.
  • chat-basic: A basic chat flow defined using class entry. It demonstrates how to create a chatbot that can remember previous interactions and use the conversation history to generate next message.
  • eval-code-quality: A example flow defined using function entry which shows how to evaluate the quality of code snippet.

DAG flow examples:

  • basic: A basic standard flow using custom python tool that calls Azure OpenAI with connection info stored in environment variables.
  • chat-basic: This example shows how to create a basic chat flow. It demonstrates how to create a chatbot that can remember previous interactions and use the conversation history to generate next message.
  • eval-basic:

Next steps


Concepts Concept Tools (`docs/concepts/concept-tools.md`)

Tools are the fundamental building blocks of a flow.

Each tool is an executable unit, basically a function to performs various tasks including but not limited to:

  • Accessing LLMs for various purposes
  • Querying databases
  • Getting information from search engines
  • Pre/post processing of data

Tools

Prompt flow provides 3 basic tools:

  • LLM: The LLM tool allows you to write custom prompts and leverage large language models to achieve specific goals, such as summarizing articles, generating customer support responses, and more.
  • Python: The Python tool enables you to write custom Python functions to perform various tasks, such as fetching web pages, processing intermediate data, calling third-party APIs, and more.
  • Prompt: The Prompt tool allows you to prepare a prompt as a string for more complex use cases or for use in conjunction with other prompt tools or python tools.

More tools

Our partners also contributes other useful tools for advanced scenarios, here are some links:

  • Vector DB Lookup: vector search tool that allows users to search top k similar vectors from vector database.
  • Faiss Index Lookup: querying within a user-provided Faiss-based vector store.

Custom tools

You can create your own tools that can be shared with your team or anyone in the world.
Learn more on Create and Use Tool Package

Next steps

For more information on the available tools and their usage, visit the our reference doc.


Concepts Concept Variants (`docs/concepts/concept-variants.md`)

With prompt flow, you can use variants to tune your prompt. In this article, you'll learn the prompt flow variants concept.

Variants

A variant refers to a specific version of a tool node that has distinct settings. Currently, variants are supported only in the LLM tool. For example, in the LLM tool, a new variant can represent either a different prompt content or different connection settings.

Suppose you want to generate a summary of a news article. You can set different variants of prompts and settings like this:

Variants Prompt Connection settings
Variant 0 Summary: {{input sentences}} Temperature = 1
Variant 1 Summary: {{input sentences}} Temperature = 0.7
Variant 2 What is the main point of this article? {{input sentences}} Temperature = 1
Variant 3 What is the main point of this article? {{input sentences}} Temperature = 0.7

By utilizing different variants of prompts and settings, you can explore how the model responds to various inputs and outputs, enabling you to discover the most suitable combination for your requirements.

Benefits of using variants

  • Enhance the quality of your LLM generation: By creating multiple variants of the same LLM node with diverse prompts and configurations, you can identify the optimal combination that produces high-quality content aligned with your needs.
  • Save time and effort: Even slight modifications to a prompt can yield significantly different results. It's crucial to track and compare the performance of each prompt version. With variants, you can easily manage the historical versions of your LLM nodes, facilitating updates based on any variant without the risk of forgetting previous iterations. This saves you time and effort in managing prompt tuning history.
  • Boost productivity: Variants streamline the optimization process for LLM nodes, making it simpler to create and manage multiple variations. You can achieve improved results in less time, thereby increasing your overall productivity.
  • Facilitate easy comparison: You can effortlessly compare the results obtained from different variants side by side, enabling you to make data-driven decisions regarding the variant that generates the best outcomes.

Next steps


Concepts Design Principles (`docs/concepts/design-principles.md`)

Design principles

When we started this project, LangChain already became popular esp. after the ChatGPT launch. One of the questions we’ve been asked is what’s the difference between prompt flow and LangChain. This article is to elucidate the reasons for building prompt flow and the deliberate design choices we have made. To put it succinctly, prompt flow is a suite of development tools for you to build LLM apps with a strong emphasis of quality through experimentations, not a framework - which LangChain is.

While LLM apps are mostly in exploration stage, Microsoft started in this area a bit earlier and we’ve had the opportunity to observe how developers are integrating LLMs into existing systems or build new applications. These invaluable insights have shaped the fundamental design principles of prompt flow.

1. Expose the prompts vs. hiding them

The core essence of LLM applications lies in the prompts themselves, at least for today. When developing a reasonably complex LLM application, the majority of development work should be β€œtuning” the prompts (note the intentional use of the term "tuning," which we will delve into further later on). Any framework or tool trying to help in this space should focus on making prompt tuning easier and more straightforward. On the other hand, prompts are very volatile, it's unlikely to write a single prompt that can work across different models or even different version of same models. Building a successful LLM-based application, you have to understand every prompt introduced, so that you can tune it when necessary. LLM is simply not powerful or deterministic enough that you can use a prompt written by others like you use libraries in traditional programming languages.

In this context, any design that tries to provide a smart function or agent by encapsulating a few prompts in a library is unlikely to yield favorable results in real-world scenarios. And hiding prompts inside a library’s code base only makes it’s hard for people to improve or tailor the prompts to suit their specific needs.

Prompt flow, being positioned as a tool, refrains from wrapping any prompts within its core codebase. The only place you will see prompts are our sample flows, which are, of course, available for adoption and utilization. Every prompt should be authored and controlled by the developers themselves, rather than relying on us.

2. A new way of work

LLMs possess remarkable capabilities that enable developers to enhance their applications without delving deep into the intricacies of machine learning. In the meantime, LLMs make these apps more stochastic, which pose new challenges to application development. Merely asserting "no exception" or "result == x" in gated tests is no longer sufficient. Adopting a new methodology and employing new tools becomes imperative to ensure the quality of LLM applications β€” an entirely novel way of working is required.

At the center of this paradigm shift is evaluation, a term frequently used in machine learning space, refers to the process of assessing the performance and quality of a trained model. It involves measuring how well the model performs on a given task or dataset, which plays a pivotal role in understanding the model's strengths, weaknesses, and overall effectiveness. Evaluation metrics and techniques vary depending on the specific task and problem domain. Some common metrics include accuracy, precision and recall, you probably already familiar with. Now the LLM apps share similarities with machine learning models, they requires an evaluation-centric approach integrated into the development workflow, with a robust set of metrics and evaluation forming the foundation for ensuring the quality of LLM applications.

Prompt flow offers a range of tools to streamline the new way of work:

  • Develop your evaluation program as Evaluation flow to calculate metrics for your app/flow, learn from our sample evaluation flows.
  • Iterate on your application flow and run evaluation flows via the SDK/CLI, allowing you to compare metrics and choose the optimal candidate for release. These iterations include trying different prompts, different LLM parameters like temperature etc. - this is referred as β€œtuning” process earlier, or sometime referred as experimentation.
  • Integrate the evaluation into your CI/CD pipeline, aligning the assertions in your gated tests with the selected metrics.

Prompt flow introduces two conceptual components to facilitate this workflow:

  • Evaluation flow: a flow type that indicates this flow is not for deploy or integrate into your app, it’s for evaluating an app/flow performance.
  • Run: every time you run your flow with data, or run an evaluation on the output of a flow, a Run object is created to manage the history and allow for comparison and additional analysis.

While new concepts introduce additional cognitive load, we firmly believe they hold greater importance compared to abstracting different LLM APIs or vector database APIs.

3. Optimize for β€œvisibility”

There are quite some interesting application patterns emerging because of LLMs, like Retrieval Augmented Generation (RAG), ReAct and more. Though how LLMs work may remain enigmatic to many developers, how LLM apps work is not - they essentially involve a series of calls to external services such as LLMs, databases, and search engines, all glued together. Architecturally there isn’t much new, patterns like RAG and ReAct are both straightforward to implement once a developer understands what they are - plain Python programs with API calls to external services can totally serve the purpose effectively.

By observing many internal use cases, we learned that deeper insight into the detail of the execution is critical. Establishing a systematic method for tracking interactions with external systems is one of design priority. Consequently, We adopted an unconventional approach - prompt flow has a YAML file describing how function calls (we call them Tools) are executed and connected into a Directed Acyclic Graph (DAG).

This approach offers several key benefits, primarily centered around enhanced visibility:

  1. During development, your flow can be visualized in an intelligible manner, enabling clear identification of any faulty components. As a byproduct, you obtain an architecturally descriptive diagram that can be shared with others.
  2. Each node in the flow has it’s internal detail visualized in a consistent way.
  3. Single nodes can be individually run or debugged without the need to rerun previous nodes.

The emphasis on visibility in prompt flow's design helps developers to gain a comprehensive understanding of the intricate details of their applications. This, in turn, empowers developers to engage in effective troubleshooting and optimization.

Despite there're some control flow features like "activate-when" to serve the needs of branches/switch-case, we do not intend to make Flow itself Turing-complete. If you want to develop an agent which is fully dynamic and guided by LLM, leveraging Semantic Kernel together with prompt flow would be a favorable option.


Dev Dev Setup (`docs/dev/dev_setup.md`)

Dev Setup

Set up process

Select either Conda or Poetry to set up your development environment.

  1. Conda environment setup
  • First create a new conda environment. Please specify python version as 3.9/3.10/3.11.
    conda create -n <env_name> python=3.9.
  • Activate the env you created.
  • In root folder, run python scripts/dev-setup/main.py to install the packages and dependencies; if you are using Visual Studio Code, it is recommended to add --vscode (which is python scripts/dev-setup/main.py --vscode) to enable VS Code to recognize the packages.
  1. Poetry environment setup
  • Install poetry. Please specify python version as 3.9/3.10/3.11.
  • Each folder under src (except the promptflow folder) is a separate package, so you need to install the dependencies for each package.
    • poetry install -C promptflow-core -E <extra> --with dev,test
    • poetry install -C promptflow-devkit -E <extra> --with dev,test
    • poetry install -C promptflow-azure -E <extra> --with dev,test

How to run tests

Set up your secrets

dev-connections.json.example is a template about connections provided in src/promptflow. You can follow these steps to refer to this template to configure your connection for the test cases:

  1. cd ./src/promptflow
  2. Run the command cp dev-connections.json.example connections.json;
  3. Replace the values in the json file with your connection info;
  4. Set the environment PROMPTFLOW_CONNECTIONS='connections.json';

After above setup process is finished. You can use pytest command to run test, for example in root folder you can:

Run tests via command

  1. Conda environment
  • Run all tests under a folder: pytest src/promptflow/tests -v, pytest src/promptflow-devkit/tests -v
  • Run a single test: pytest src/promptflow/tests/promptflow_test/e2etests/test_executor.py::TestExecutor::test_executor_basic_flow -v
  1. Poetry environment: there is limitation for running tests in src/promptflow folder, you can only run tests under other package folders.
  • for example: under the target folder promptflow-devkit, you can run poetry run pytest tests/sdk_cli_test -v

Run tests in VSCode


Conda environment

  1. Set up your python interperter
  • Open the Command Palette (Ctrl+Shift+P) and select Python: Select Interpreter.

  • Select existing conda env which you created previously.

  1. Set up your test framework and directory
  • Open the Command Palette (Ctrl+Shift+P) and select Python: Configure Tests.

  • Select pytest as test framework.

  • Select Root directory as test directory.

  1. Exclude specific test folders.

You can exclude specific test folders if you don't have some extra dependency to avoid VS Code's test discovery fail.
For example, if you don't have azure dependency, you can exclude sdk_cli_azure_test.
Open .vscode/settings.json, write "--ignore=src/promptflow/tests/sdk_cli_azure_test" to "python.testing.pytestArgs".

  1. Click the Run Test button on the left

Run tests in pycharm

  1. Set up your pycharm python interpreter

  2. Select existing conda env which you created previously

  3. Run test, right-click the test name to run, or click the green arrow button on the left.


Poetry environment

VSCode could pick up the correct environment automatically if you open vscode/pycharm under the package folders.

There are some limitations currently, intellisense may not work properly in poetry environment.

PyCharm behaves differently from VSCode, it will automatically picks up the correct environment.

How to write docstring

A clear and consistent API documentation is crucial for the usability and maintainability of our codebase. Please refer to API Documentation Guidelines to learn how to write docstring when developing the project.

How to write tests

  • Put all test data/configs under src/promptflow/tests/test_configs.
  • Write unit tests:
    • Flow run: src/promptflow/tests/sdk_cli_test/unittest/
    • Flow run in azure: src/promptflow/tests/sdk_cli_azure_test/unittest/
  • Write e2e tests:
    • Flow run: src/promptflow/tests/sdk_cli_test/e2etests/
    • Flow run in azure: src/promptflow/tests/sdk_cli_azure_test/e2etests/
  • Test file name and the test case name all start with test_.
  • A basic test example, see test_connection.py.

Test structure

Tests are under corresponding source folder, and test_configs are shared among different test folders:

  • src/promptflow/
    • test_configs/
      • connections/
      • datas/
      • flows/
      • runs/
      • wrong_flows/
      • wrong_tools/
  • src/promptflow-core/
    • tests/
      • core/ # Basic test with promptflow-core installed.
        • e2etests/
        • unittests/
      • azureml-serving/ # Test with promptflow-core[azureml-serving] installed.
        • e2etests/
        • unittests/
      • executor-service/ # Test with promptflow-core[executor-service] installed.
        • e2etests/
        • unittests/
  • src/promptflow-devkit/
    • tests/
      • sdk_cli_tests/
        • e2etests/
        • unittests/
  • src/promptflow-azure/
    • tests/
      • sdk_cli_azure_test/
        • e2etests/
        • unittests/

Principal #1: Put the tests in the same folder as the code they are testing, to ensure code can work within minor environment requirements.

For example, you write code requires basic promptflow-core package, then put the tests in promptflow-core/tests/core, DO NOT put it in the promptflow-devkit or promptflow-azure.

Principal #2: Setup separate workflow for tests with extra-requires.

For example, you want to test promptflow-core[azureml-serving], then add a new test folder promptflow-core/tests/azureml-serving to test the azure related code,
and add new test steps and environment setup step into promptflow-core-test.yml for that folder. DO NOT update the environment of promptflow-core basic test directly.

Record and replay tests

Please refer to Replay End-to-End Tests to learn how to record and replay tests.


Dev Documentation Guidelines (`docs/dev/documentation_guidelines.md`)

Promptflow Reference Documentation Guide

Overview

This guide describes how to author Python docstrings for promptflow public interfaces. See our doc site at Promptflow API reference documentation.

Principles

  • Coverage: Every public object must have a docstring. For private objects, docstrings are encouraged but not required.
  • Style: All docstrings should be written in Sphinx style noting all types and if any exceptions are raised.
  • Relevance: The documentation is up-to-date and relevant to the current version of the product.
  • Clarity: The documentation is written in clear, concise language that is easy to understand.
  • Consistency: The documentation has a consistent format and structure, making it easy to navigate and follow.

How to write the docstring

First please read through Sphinx style to have a basic understanding of sphinx style docstring.

Write class docstring

Let's start with a class example:

python
from typing import Dict, Optional, Union
from promptflow.client import PFClient

class MyClass:
    """One-line summary of the class.

    More detailed explanation of the class. May include below notes, admonitions, code blocks.

    .. note::

        Here are some notes to show, with a nested python code block:

        .. code-block:: python

            from promptflow import MyClass, PFClient
            obj = MyClass(PFClient())

    .. admonition:: [Title of the admonition]

        Here are some admonitions to show.

    :param client: Descrition of the client.
    :type client: ~promptflow.PFClient
    :param param_int: Description of the parameter.
    :type param_int: Optional[int]
    :param param_str: Description of the parameter.
    :type param_str: Optional[str]
    :param param_dict: Description of the parameter.
    :type param_dict: Optional[Dict[str, str]]
    """
    def __init__(
        client: PFClient,
        param_int: Optional[int] = None,
        param_str: Optional[str] = None,
        param_dict: Optional[Dict[str, str]] = None,
    ) -> None:
        """No docstring for __init__, it should be written in class definition above."""
        ...

Notes:

  1. One-line summary is required. It should be clear and concise.

  2. Detailed explanation is encouraged but not required. This part may or may not include notes, admonitions and code blocks.

    • The format like .. note:: is called directive. Directives are a mechanism to extend the content of reStructuredText. Every directive declares a block of content with specific role. Start a new line with .. directive_name:: to use the directive.
    • The directives used in the sample(note/admonition/code-block) should be enough for basic usage of docstring in our project. But you are welcomed to explore more Directives.
  3. Parameter description and type is required.

    • A pair of :param [ParamName]: and :type [ParamName]: is required.
    • If the type is a promptflow public class, use the full path to the class and prepend it with a "~". This will create a link when the documentation is rendered on the doc site that will take the user to the class reference documentation for more information.
      text
      :param client: Descrition of the client.
      :type client: ~promptflow.PFClient
    • Use Union/Optional when appropriate in function declaration. And use the same annotaion after :type [ParamName]:
      text
      :type param_int: Optional[int]
  4. For classes, include docstring in definition only. If you include a docstring in both the class definition and the constructor (init method) docstrings, it will show up twice in the reference docs.

  5. Constructors (def __init__) should return None, per PEP 484 standards.

  6. To create a link for promptflow class on our doc site. ~promptflow.xxx.MyClass alone only works after :type [ParamName] and :rtype:. If you want to achieve the same effect in docstring summary, you should use it with :class::

    python
    """
    An example to achieve link effect in summary for :class:`~promptflow.xxx.MyClass`
    For function, use :meth:`~promptflow.xxx.my_func`
    """
  7. There are some tricks to highlight the content in your docstring:

    • Single backticks (`): Single backticks are used to represent inline code elements within the text. It is typically used to highlight function names, variable names, or any other code elements within the documentation.
    • Double backticks(``): Double backticks are typically used to highlight a literal value.
  8. If there are any class level constants you don't want to expose to doc site, make sure to add _ in front of the constant to hide it.

Write function docstring

python
from typing import Optional

def my_method(param_int: Optional[int] = None) -> int:
    """One-line summary

    Detailed explanations.

    :param param_int: Description of the parameter.
    :type param_int: int
    :raises [ErrorType1]: [ErrorDescription1]
    :raises [ErrorType2]: [ErrorDescription2]
    :return: Description of the return value.
    :rtype: int
    """
    ...

In addition to class docstring notes:

  1. Function docstring should include return values.
    • If return type is promptflow class, we should also use ~promptflow.xxx.[ClassName].
  2. Function docstring should include exceptions that may be raised in this function.
    • If exception type is PromptflowException, use ~promptflow.xxx.[ExceptionName]
    • If multiple exceptions are raised, just add new lines of :raises, see the example above.

How to build doc site locally

You can build the documentation site locally to preview the final effect of your docstring on the rendered site. This will provide you with a clear understanding of how your docstring will appear on our site once your changes are merged into the main branch.

  1. Setup your dev environment, see dev_setup for details. Sphinx will load all source code to process docstring.
    • Skip this step if you just want to build the doc site without reference doc, but do remove -WithReferenceDoc from the command in step 3.
  2. Install langchain package since it is used in our code but not covered in dev_setup.
  3. Open a powershell, activate the conda env and navigate to <repo-root>/scripts/docs , run doc_generation.ps1:
    pwsh
    cd scripts\docs
    .\doc_generation.ps1 -WithReferenceDoc -WarningAsError
    • For the first time you execute this command, it will take some time to install sphinx dependencies. After the initial installation, next time you can add param -SkipInstall to above command to save some time for dependency check.
  4. Check warnings/errors in the build log, fix them if any, then build again.
  5. Open scripts/docs/_build/index.html to preview the local doc site.

Additional comments

  • Utilities: The autoDocstring VSCode extension or GitHub Copilot can help autocomplete in this style for you.

  • Advanced principles

    • Accuracy: The documentation accurately reflects the features and functionality of the product.
    • Completeness: The documentation covers all relevant features and functionality of the product.
    • Demonstration: Every docstring should include an up-to-date code snippet that demonstrates how to use the product effectively.

References


Dev Replay E2e Test (`docs/dev/replay-e2e-test.md`)

Replay end-to-end tests

  • This document introduces replay tests for those located in sdk_cli_azure_test and sdk_cli_test.
  • The primary purpose of replay tests is to avoid the need for credentials, Azure workspaces, OpenAI tokens, and to directly test prompt flow behavior.
  • Although there are different techniques behind recording/replaying, there are some common steps to run the tests in replay mode.
  • The key handle of replay tests is the environment variable PROMPT_FLOW_TEST_MODE.

How to run tests in replay mode

After cloning the full repo and setting up the proper test environment following dev_setup.md, run the following command in the root directory of the repo:

  1. If you have changed/affected tests in sdk_cli_test : Copy or rename the file dev-connections.json.example to connections.json in the same folder.
    • There are some python package version requirements for running the replay/record tests. It needs pydantic >= 2.0.0.
  2. In your Python environment, set the environment variable PROMPT_FLOW_TEST_MODE to 'replay' and run the test(s).

These tests should work properly without any real connection settings.

Test modes

There are 3 representative values of the environment variable PROMPT_FLOW_TEST_MODE

  • live: Tests run against the real backend, which is the way traditional end-to-end tests do.
  • record: Tests run against the real backend, and network traffic will be sanitized (filter sensitive and unnecessary requests/responses) and recorded to local files (recordings).
  • replay: There is no real network traffic between SDK/CLI and the backend, tests run against local recordings.

Supported modules

Update test recordings

To record a test, don’t forget to clone the full repo and set up the proper test environment following dev_setup.md:

  1. Ensure you have installed dev version of promptflow-recording package.
    • If it is not installed, run pip install -e src/promptflow-recording in the root directory of the repo.
  2. Prepare some data.
    • If you have changed/affected tests in sdk_cli_test: Copy or rename the file dev-connections.json.example to connections.json in the same folder.
    • If you have changed/affected tests in sdk_cli_azure_test: prepare your Azure ML workspace, make sure your Azure CLI logged in, and set the environment variable PROMPT_FLOW_SUBSCRIPTION_ID, PROMPT_FLOW_RESOURCE_GROUP_NAME, PROMPT_FLOW_WORKSPACE_NAME and PROMPT_FLOW_RUNTIME_NAME (if needed) pointing to your workspace.
  3. Record the test.
    • Specify the environment variable PROMPT_FLOW_TEST_MODE to 'record'. If you have a .env file, we recommend specifying it there. Here is an example .env file. Then, just run the test that you want to record.
  4. Once the test completed.
    • If you have changed/affected tests in sdk_cli_azure_test: There should be one new YAML file located in Azure recording folder, containing the network traffic of the test.
    • If you have changed/affected tests in sdk_cli_test: There may be changes in the folder Local recording folder. Don’t worry if there are no changes, because similar LLM calls may have been recorded before.

Techniques behind replay test

Sdk_cli_azure_test

End-to-end tests for pfazure aim to test the behavior of the PromptFlow SDK/CLI as it interacts with the service. This process can be time-consuming, error-prone, and require credentials (which are unavailable to pull requests from forked repositories); all of these go against our intention for a smooth development experience.

Therefore, we introduce replay tests, which leverage VCR.py to record all required network traffic to local files and replay during tests. In this way, we avoid the need for credentials, speed up, and stabilize the test process.

Sdk_cli_test

sdk_cli_test often doesn’t use a real backend. It will directly invokes LLM calls from localhost. Thus the key target of replay tests is to avoid the need for OpenAI tokens. If you have OpenAI / Azure OpenAI tokens yourself, you can try recording the tests. Record Storage will not record your own LLM connection, but only the inputs and outputs of the LLM calls.

There are also limitations. Currently, recorded calls are:

  • AzureOpenAI calls
  • OpenAI calls
  • tool name "fetch_text_content_from_url" and tool name "my_python_tool"

Dev Rotate Aoai Keys (`docs/dev/rotate_aoai_keys.md`)

Here is a checklist to rotate the AOAI keys:

  1. Go to the well known URL of the AOAI service.
  2. Check the secondary keys (This is the key used in the following days).
  3. Change promptflow-eastus2euap Connections
  4. Also Change promptflow-eastus Connections
  5. Save the key in the well known key vault.
  6. Save the key in the github secrets, to mask the key.
  7. Rotate the DEPRECATED the leaked key in the AOAI service.

How To Guides Enable Streaming Mode (`docs/how-to-guides/enable-streaming-mode.md`)

Use streaming endpoints deployed from prompt flow

In prompt flow, you can deploy flow as REST endpoint for real-time inference.

When consuming the endpoint by sending a request, the default behavior is that the online endpoint will keep waiting until the whole response is ready, and then send it back to the client. This can cause a long delay for the client and a poor user experience.

To avoid this, you can use streaming when you consume the endpoints. Once streaming enabled, you don't have to wait for the whole response ready. Instead, the server will send back the response in chunks as they are generated. The client can then display the response progressively, with less waiting time and more interactivity.

This article will describe the scope of streaming, how streaming works, and how to consume streaming endpoints.

Create a streaming enabled flow

If you want to use the streaming mode, you need to create a flow that has a node that produces a string generator as the flow’s output. A string generator is an object that can return one string at a time when requested. You can use the following types of nodes to create a string generator:

  • LLM node: This node uses a large language model to generate natural language responses based on the input.
    jinja
    {# Sample prompt template for LLM node #}
    
    # system:
    You are a helpful assistant.
    
    # user:
    {{question}}
  • Python tools node: This node allows you to write custom Python code that can yield string outputs. You can use this node to call external APIs or libraries that support streaming. For example, you can use this code to echo the input word by word:
    python
    from promptflow.core import tool
    
    # Sample code echo input by yield in Python tool node
    
    @tool
    def my_python_tool(paragraph: str) -> str:
        yield "Echo: "
        for word in paragraph.split():
            yield word + " "

In this guide, we will use the "Chat with Wikipedia" sample flow as an example. This flow processes the user’s question, searches Wikipedia for relevant articles, and answers the question with information from the articles. It uses streaming mode to show the progress of the answer generation.

Deploy the flow as an online endpoint

To use the streaming mode, you need to deploy your flow as an online endpoint. This will allow you to send requests and receive responses from your flow in real time.

Follow this guide to deploy your flow as an online endpoint.

[!NOTE]

You can follow this document to deploy an online endpoint.
Please deploy with runtime environment version later than version 20230816.v10.
You can check your runtime version and update runtime in the run time detail page.

Understand the streaming process

When you have an online endpoint, the client and the server need to follow specific principles for content negotiation to utilize the streaming mode:

Content negotiation is like a conversation between the client and the server about the preferred format of the data they want to send and receive. It ensures effective communication and agreement on the format of the exchanged data.

To understand the streaming process, consider the following steps:

  • First, the client constructs an HTTP request with the desired media type included in the Accept header. The media type tells the server what kind of data format the client expects. It's like the client saying, "Hey, I'm looking for a specific format for the data you'll send me. It could be JSON, text, or something else." For example, application/json indicates a preference for JSON data, text/event-stream indicates a desire for streaming data, and */* means the client accepts any data format.

    [!NOTE]

    If a request lacks an Accept header or has empty Accept header, it implies that the client will accept any media type in response. The server treats it as */*.

  • Next, the server responds based on the media type specified in the Accept header. It's important to note that the client may request multiple media types in the Accept header, and the server must consider its capabilities and format priorities to determine the appropriate response.

    • First, the server checks if text/event-stream is explicitly specified in the Accept header:
      • For a stream-enabled flow, the server returns a response with a Content-Type of text/event-stream, indicating that the data is being streamed.
      • For a non-stream-enabled flow, the server proceeds to check for other media types specified in the header.
    • If text/event-stream is not specified, the server then checks if application/json or */* is specified in the Accept header:
      • In such cases, the server returns a response with a Content-Type of application/json, providing the data in JSON format.
    • If the Accept header specifies other media types, such as text/html:
      • The server returns a 424 response with a PromptFlow runtime error code UserError and a runtime HTTP status 406, indicating that the server cannot fulfill the request with the requested data format.

      Note: Please refer handle errors for details.

  • Finally, the client checks the Content-Type response header. If it is set to text/event-stream, it indicates that the data is being streamed.

Let’s take a closer look at how the streaming process works. The response data in streaming mode follows the format of server-sent events (SSE).

The overall process works as follows:

0. The client sends a message to the server.

text
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream

{
    "question": "Hello",
    "chat_history": []
}

[!NOTE]

The Accept header is set to text/event-stream to request a stream response.

1. The server sends back the response in streaming mode.

text
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked

data: {"answer": ""}

data: {"answer": "Hello"}

data: {"answer": "!"}

data: {"answer": " How"}

data: {"answer": " can"}

data: {"answer": " I"}

data: {"answer": " assist"}

data: {"answer": " you"}

data: {"answer": " today"}

data: {"answer": " ?"}

data: {"answer": ""}

Note that the Content-Type is set to text/event-stream; charset=utf-8, indicating the response is an event stream.

The client should decode the response data as server-sent events and display them incrementally. The server will close the HTTP connection after all the data is sent.

Each response event is the delta to the previous event. It is recommended for the client to keep track of the merged data in memory and send them back to the server as chat history in the next request.

2. The client sends another chat message, along with the full chat history, to the server.

text
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream

{
    "question": "Glad to know you!",
    "chat_history": [
        {
            "inputs": {
                "question": "Hello"
            },
            "outputs": {
                "answer": "Hello! How can I assist you today?"
            }
        }
    ]
}

3. The server sends back the answer in streaming mode.

text
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked

data: {"answer": ""}

data: {"answer": "Nice"}

data: {"answer": " to"}

data: {"answer": " know"}

data: {"answer": " you"}

data: {"answer": " too"}

data: {"answer": "!"}

data: {"answer": " Is"}

data: {"answer": " there"}

data: {"answer": " anything"}

data: {"answer": " I"}

data: {"answer": " can"}

data: {"answer": " help"}

data: {"answer": " you"}

data: {"answer": " with"}

data: {"answer": "?"}

data: {"answer": ""}

4. The chat continues in a similar way.

Handle errors

The client should check the HTTP response code first. See this table for common error codes returned by online endpoints.

If the response code is "424 Model Error", it means that the error is caused by the model’s code. The error response from a PromptFlow model always follows this format:

json
{
  "error": {
    "code": "UserError",
    "message": "Media type text/event-stream in Accept header is not acceptable. Supported media type(s) - application/json",
  }
}
  • It is always a JSON dictionary with only one key "error" defined.
  • The value for "error" is a dictionary, containing "code", "message".
  • "code" defines the error category. Currently, it may be "UserError" for bad user inputs and "SystemError" for errors inside the service.
  • "message" is a description of the error. It can be displayed to the end user.

How to consume the server-sent events

Consume using Python

In this sample usage, we are using the SSEClient class. This class is not a built-in Python class and needs to be installed separately. You can install it via pip:

bash
pip install sseclient-py

A sample usage would like:

python
import requests
from sseclient import SSEClient
from requests.exceptions import HTTPError

try:
    response = requests.post(url, json=body, headers=headers, stream=stream)
    response.raise_for_status()

    content_type = response.headers.get('Content-Type')
    if "text/event-stream" in content_type:
        client = SSEClient(response)
        for event in client.events():
            # Handle event, i.e. print to stdout
    else:
        # Handle json response

except HTTPError:
    # Handle exceptions

Consume using JavaScript

There are several libraries to consume server-sent events in JavaScript. Here is one of them as an example.

A sample chat app using Python

Here is a sample chat app written in Python.
(Click here to view the source code.)

Advance usage - hybrid stream and non-stream flow output

Sometimes, you may want to get both stream and non-stream results from a flow output. For example, in the β€œChat with Wikipedia” flow, you may want to get not only LLM’s answer, but also the list of URLs that the flow searched. To do this, you need to modify the flow to output a combination of stream LLM’s answer and non-stream URL list.

In the sample "Chat With Wikipedia" flow, the output is connected to the LLM node augmented_chat. To add the URL list to the output, you need to add an output field with the name url and the value ${get_wiki_url.output}.

The output of the flow will be a non-stream field as the base and a stream field as the delta. Here is an example of request and response.

0. The client sends a message to the server.

text
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream
{
    "question": "When was ChatGPT launched?",
    "chat_history": []
}

1. The server sends back the answer in streaming mode.

text
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked

data: {"url": ["https://en.wikipedia.org/w/index.php?search=ChatGPT", "https://en.wikipedia.org/w/index.php?search=GPT-4"]}

data: {"answer": ""}

data: {"answer": "Chat"}

data: {"answer": "G"}

data: {"answer": "PT"}

data: {"answer": " was"}

data: {"answer": " launched"}

data: {"answer": " on"}

data: {"answer": " November"}

data: {"answer": " "}

data: {"answer": "30"}

data: {"answer": ","}

data: {"answer": " "}

data: {"answer": "202"}

data: {"answer": "2"}

data: {"answer": "."}

data: {"answer": " \n\n"}

...

data: {"answer": "PT"}

data: {"answer": ""}

2. The client sends another chat message, along with the full chat history, to the server.

text
POST https://<your-endpoint>.inference.ml.azure.com/score
Content-Type: application/json
Authorization: Bearer <key or token of your endpoint>
Accept: text/event-stream
{
    "question": "When did OpenAI announce GPT-4? How long is it between these two milestones?",
    "chat_history": [
        {
            "inputs": {
                "question": "When was ChatGPT launched?"
            },
            "outputs": {
                "url": [
                    "https://en.wikipedia.org/w/index.php?search=ChatGPT",
                    "https://en.wikipedia.org/w/index.php?search=GPT-4"
                ],
                "answer": "ChatGPT was launched on November 30, 2022. \n\nSOURCES: https://en.wikipedia.org/w/index.php?search=ChatGPT"
            }
        }
    ]
}

3. The server sends back the answer in streaming mode.

text
HTTP/1.1 200 OK
Content-Type: text/event-stream; charset=utf-8
Connection: close
Transfer-Encoding: chunked

data: {"url": ["https://en.wikipedia.org/w/index.php?search=Generative pre-trained transformer ", "https://en.wikipedia.org/w/index.php?search=Microsoft "]}

data: {"answer": ""}

data: {"answer": "Open"}

data: {"answer": "AI"}

data: {"answer": " released"}

data: {"answer": " G"}

data: {"answer": "PT"}

data: {"answer": "-"}

data: {"answer": "4"}

data: {"answer": " in"}

data: {"answer": " March"}

data: {"answer": " "}

data: {"answer": "202"}

data: {"answer": "3"}

data: {"answer": "."}

data: {"answer": " Chat"}

data: {"answer": "G"}

data: {"answer": "PT"}

data: {"answer": " was"}

data: {"answer": " launched"}

data: {"answer": " on"}

data: {"answer": " November"}

data: {"answer": " "}

data: {"answer": "30"}

data: {"answer": ","}

data: {"answer": " "}

data: {"answer": "202"}

data: {"answer": "2"}

data: {"answer": "."}

data: {"answer": " The"}

data: {"answer": " time"}

data: {"answer": " between"}

data: {"answer": " these"}

data: {"answer": " two"}

data: {"answer": " milestones"}

data: {"answer": " is"}

data: {"answer": " approximately"}

data: {"answer": " "}

data: {"answer": "3"}

data: {"answer": " months"}

data: {"answer": ".\n\n"}

...

data: {"answer": "Chat"}

data: {"answer": "G"}

data: {"answer": "PT"}

data: {"answer": ""}

How To Guides Execute Flow As A Function (`docs/how-to-guides/execute-flow-as-a-function.md`)

Execute flow as a function

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Overview

Promptflow allows you to load a flow and use it as a function in your code.
This feature is useful when building a service on top of a flow, reference here for a simple example service with flow function consumption.

Load and invoke the flow function

To use the flow-as-function feature, you first need to load a flow using the load_flow function.
Then you can consume the flow object like a function by providing key-value arguments for it.

python
f = load_flow("../../examples/flows/standard/web-classification/")
f(url="sample_url")

Config the flow with context

You can overwrite some flow configs before flow function execution by setting flow.context.

Load flow as a function with in-memory connection override

By providing a connection object to flow context, flow won't need to get connection in execution time, which can save time when for cases where flow function need to be called multiple times.

python
from promptflow.entities import AzureOpenAIConnection

connection_obj = AzureOpenAIConnection(
    name=conn_name,
    api_key=api_key,
    api_base=api_base,
    api_type="azure",
    api_version=api_version,
)
# no need to create the connection object.  
f.context = FlowContext(
    connections={"classify_with_llm": {"connection": connection_obj}}
)

Local flow as a function with flow inputs override

By providing overrides, the original flow dag will be updated in execution time.

python
f.context = FlowContext(
    # node "fetch_text_content_from_url" will take inputs from the following command instead of from flow input
    overrides={"nodes.fetch_text_content_from_url.inputs.url": sample_url},
)

Note, the overrides are only doing YAML content replacement on original flow.dag.yaml.
If the flow.dag.yaml become invalid after overrides, validation error will be raised when executing.

Load flow as a function with streaming output

After set streaming in flow context, the flow function will return an iterator to stream the output.

python
f = load_flow(source="../../examples/flows/chat/chat-basic/")
f.context.streaming = True
result = f(
    chat_history=[
        {
            "inputs": {"chat_input": "Hi"},
            "outputs": {"chat_output": "Hello! How can I assist you today?"},
        }
    ],
    question="How are you?",
)


answer = ""
# the result will be a generator, iterate it to get the result
for r in result["answer"]:
    answer += r

Reference our sample for usage.

Flow with multiple overrides

Note: the flow context configs may affect each other in some cases. For example, using connection & overrides to override same node.
The behavior is undefined for those scenarios. Pleas avoid such usage.

python
# overriding `classify_with_llm`'s connection and inputs in the same time will lead to undefined behavior.
f.context = FlowContext(
    connections={"classify_with_llm": {"connection": connection_obj}},
    overrides={"nodes.classify_with_llm.inputs.url": sample_url}
)

Next steps

Learn more about:


How To Guides Faq (`docs/how-to-guides/faq.md`)

Frequency asked questions (FAQ)

General

Stable vs experimental

Prompt flow provides both stable and experimental features in the same SDK.

Feature status Description
Stable features Production ready These features are recommended for most use cases and production environments. They are updated less frequently then experimental features.
Experimental features Developmental These features are newly developed capabilities & updates that may not be ready or fully tested for production usage. While the features are typically functional, they can include some breaking changes. Experimental features are used to iron out SDK breaking bugs, and will only receive updates for the duration of the testing period. Experimental features are also referred to as features that are in preview. As the name indicates, the experimental (preview) features are for experimenting and is not considered bug free or stable. For this reason, we only recommend experimental features to advanced users who wish to try out early versions of capabilities and updates, and intend to participate in the reporting of bugs and glitches.

OpenAI 1.x support

Please use the following command to upgrade promptflow for openai 1.x support:

text
pip install promptflow>=1.1.0
pip install promptflow-tools>=1.0.0

Note that the command above will upgrade your openai package a version later than 1.0.0,
which may introduce breaking changes to custom tool code.

Reach OpenAI migration guide for more details.

Promptflow 1.8.0 upgrade guide

Before upgrading to promptflow version 1.8.0 or later, it's important to first uninstall any existing installations of promptflow and its sub-packages.
This ensures a clean installation of the new version without any conflicts.

bash
pip uninstall -y promptflow promptflow-core promptflow-devkit promptflow-azure # uninstall promptflow and its sub-packages
pip install 'promptflow>=1.8.0' # install promptflow version 1.8.0 or later

Reason for 'pip install promptflow>=1.8.0' or 'pf upgrade' directly not working:

promptflow package has been split into multiple packages. When installing promptflow, you will get the following packages:

  • promptflow:
    • promptflow-tracing: Tracing capability for promptflow.
    • promptflow-core: Core functionality to run flow.
    • promptflow-devkit: Development kit for promptflow.
    • promptflow-azure: Azure extra requires(promptflow[azure]) for promptflow to integrate with Azure.

When upgrading promptflow from an existing version to promptflow 1.8.0, pip will remove the old promptflow after installing promptflow subpackages,
which caused subpackage files got wrongly removed.

Troubleshooting

Connection creation failed with StoreConnectionEncryptionKeyError

text
Connection creation failed with StoreConnectionEncryptionKeyError: System keyring backend service not found in your operating system. See https://pypi.org/project/keyring/ to install requirement for different operating system, or 'pip install keyrings.alt' to use the third-party backend.

This error raised due to keyring can't find an available backend to store keys.
For example macOS Keychain and Windows Credential Locker
are valid keyring backends.

To resolve this issue, install the third-party keyring backend or write your own keyring backend, for example:
pip install keyrings.alt

For more detail about keyring third-party backend, please refer to 'Third-Party Backends' in keyring.

Pf visualize show error: "tcgetpgrp failed: Not a tty"

If you are using WSL, this is a known issue for webbrowser under WSL; see this issue for more information. Please try to upgrade your WSL to 22.04 or later, this issue should be resolved.

If you are still facing this issue with WSL 22.04 or later, or you are not even using WSL, please open an issue to us.

Installed tool not appearing in VSCode Extension tool list

After installing a tool package via pip install [tool-package-name], the new tool may not immediately appear in the tool list within the VSCode Extension, as shown below:

This is often due to outdated cache. To refresh the tool list and make newly installed tools visible:

  1. Open the VSCode Extension window.

  2. Bring up the command palette by pressing "Ctrl+Shift+P".

  3. Type and select the "Developer: Reload Webviews" command.

  4. Wait a moment for the tool list refreshing.

Reloading clears the previous cache and populates the tool list with any newly installed tools. So that the missing tools are now visible.

Set logging level

Promptflow uses logging module to log messages. You can set logging level via environment variable PF_LOGGING_LEVEL, valid values includes CRITICAL, ERROR, WARNING, INFO, DEBUG, default to INFO.
Below is the serving logs after setting PF_LOGGING_LEVEL to DEBUG:

Compare to the serving logs with WARNING level:

Set logging format

Promptflow uses the following log format and datetime format by default:

  • Log format: %(asctime)s %(process)7d %(name)-18s %(levelname)-8s %(message)s
  • Datetime format: %Y-%m-%d %H:%M:%S %z

You can customize the log format with the PF_LOG_FORMAT environment variable, and the datetime format with PF_LOG_DATETIME_FORMAT. These variables can also be defined in a flow yaml file or set directly in the environment.

Set environment variables

Currently, promptflow supports the following environment variables:

PF_WORKER_COUNT

Effective for batch run only, count of parallel workers in batch run execution.

The default value is 4 (was 16 when promptflow<1.4.0)

Please take the following points into consideration when changing it:

  1. The concurrency should not exceed the total data rows count. Otherwise, the execution may slow down due to additional time spent on process startup and shutdown.

  2. High parallelism may cause the underlying API call to reach the rate limit of your LLM endpoint. In which case you can decrease the PF_WORKER_COUNT or increase the rate limit. Please refer to this doc on quota management. Then you can refer to this expression to set up the concurrency.

text
PF_WORKER_COUNT <= TPM * duration_seconds / token_count / 60

TPM: token per minute, capacity rate limit of your LLM endpoint

duration_seconds: single flow run duration in seconds

token_count: single flow run token count

For example, if your endpoint TPM (token per minute) is 50K, the single flow run takes 10k tokens and runs for 30s, pls do not set up PF_WORKER_COUNT bigger than 2. This is a rough estimation. Please also consider collboaration (teammates use the same endpoint at the same time) and tokens consumed in deployed inference endpoints, playground and other cases which might send request to your LLM endpoints.

PF_BATCH_METHOD

Valid for batch run only. Optional values: 'spawn', 'fork'.

spawn

  1. The child processes will not inherit resources of the parent process, therefore, each process needs to reinitialize the resources required for the flow, which may use more system memory.

  2. Starting a process is slow because it will take some time to initialize the necessary resources.

fork

  1. Use the copy-on-write mechanism, the child processes will inherit all the resources of the parent process, thereby using less system memory.

  2. The process starts faster as it doesn't need to reinitialize resources.

Note: Windows only supports spawn, Linux and macOS support both spawn and fork.

How to configure environment variables

  1. Configure environment variables in flow.dag.yaml. Example:
text
inputs: []
    outputs: []
    nodes: []
    environment_variables:
    β€― PF_WORKER_COUNT: 2
    β€― PF_BATCH_METHOD: "spawn"
    β€― MY_CUSTOM_SETTING: my_custom_value
  1. Specify environment variables when submitting runs.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Use this parameter: --environment-variable to specify environment variables.
Example: --environment-variable PF_WORKER_COUNT="2" PF_BATCH_METHOD="spawn".

:::

:::{tab-item} SDK
:sync: SDK

Specify environment variables when creating run. Example:

python
pf = PFClient(
        credential=credential,
        subscription_id="<SUBSCRIPTION_ID>",
        resource_group_name="<RESOURCE_GROUP>",
        workspace_name="<AML_WORKSPACE_NAME>",
    )

    flow = "web-classification"
    data = "web-classification/data.jsonl"

    environment_variables = {"PF_WORKER_COUNT": "2", "PF_BATCH_METHOD": "spawn"}

    # create run
    base_run = pf.run(
        flow=flow,
        data=data,
        environment_variables=environment_variables,
    )

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

VSCode Extension supports specifying environment variables only when submitting batch runs.
Specify environment variables in batch_run_create.yaml. Example:

yaml
name: flow_name
    display_name: display_name
    flow: flow_folder
    data: data_file
    column_mapping:
        customer_info: <Please select a data input>
        history: <Please select a data input>
    environment_variables:
        PF_WORKER_COUNT: "2"
        PF_BATCH_METHOD: "spawn"

:::

::::

Priority

The environment variables specified when submitting runs always takes precedence over the environment variables in the flow.dag.yaml file.


How To Guides Manage Connections (`docs/how-to-guides/manage-connections.md`)

Manage connections

Connection helps securely store and manage secret keys or other sensitive credentials required for interacting with LLM (Large Language Models) and other external tools, for example, Azure Content Safety.

:::{note}
This document target for manage connections locally. To use Azure AI connections locally, refer to this guide.
:::

Connection types

There are multiple types of connections supported in promptflow, which can be simply categorized into strong type connection and custom connection. The strong type connection includes AzureOpenAIConnection, OpenAIConnection, etc. The custom connection is a generic connection type that can be used to store custom defined credentials.

We are going to use AzureOpenAIConnection as an example for strong type connection, and CustomConnection to show how to manage connections.

Create a connection

:::{note}
If you are using WSL or other OS without default keyring storage backend, you may encounter StoreConnectionEncryptionKeyError, please refer to FAQ for the solutions.
:::

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
Each of the strong type connection has a corresponding yaml schema, the example below shows the AzureOpenAIConnection yaml:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/AzureOpenAIConnection.schema.json
name: azure_open_ai_connection
type: azure_open_ai
api_key: "<to-be-replaced>"
api_base: "https://<name>.openai.azure.com/"
api_type: "azure"
api_version: "2023-03-15-preview"

The custom connection yaml will have two dict fields for secrets and configs, the example below shows the CustomConnection yaml:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/CustomConnection.schema.json
name: custom_connection
type: custom
configs:
  endpoint: "<your-endpoint>"
  other_config: "other_value"
secrets:  # required
  my_key: "<your-api-key>"

After preparing the yaml file, use the CLI command below to create them:

bash
# Override keys with --set to avoid yaml file changes
pf connection create -f <path-to-azure-open-ai-connection> --set api_key=<your-api-key>
# Create the custom connection
pf connection create -f <path-to-custom-connection> --set configs.endpoint=<endpoint> secrets.my_key=<your-api-key>

The expected result is as follows if the connection created successfully.

:::

:::{tab-item} SDK
:sync: SDK
Using SDK, each connection type has a corresponding class to create a connection. The following code snippet shows how to import the required class and create the connection:

python
from promptflow.client import PFClient
from promptflow.entities import AzureOpenAIConnection, CustomConnection

# Get a pf client to manage connections
pf = PFClient()

# Initialize an AzureOpenAIConnection object
connection = AzureOpenAIConnection(
    name="my_azure_open_ai_connection", 
    api_key="<your-api-key>", 
    api_base="<your-endpoint>",
    api_version="2023-03-15-preview"
)

# Create the connection, note that api_key will be scrubbed in the returned result
result = pf.connections.create_or_update(connection)
print(result)

# Initialize a custom connection object
connection = CustomConnection(
    name="my_custom_connection", 
    # Secrets is a required field for custom connection
    secrets={"my_key": "<your-api-key>"},
    configs={"endpoint": "<your-endpoint>", "other_config": "other_value"}
)

# Create the connection, note that all secret values will be scrubbed in the returned result
result = pf.connections.create_or_update(connection)
print(result)

:::

:::{tab-item} VS Code Extension
:sync: VSC

On the VS Code primary sidebar > prompt flow pane. You can find the connections pane to manage your local connections. Click the "+" icon on the top right of it and follow the popped out instructions to create your new connection.

:::
::::

Update a connection

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
The commands below show how to update existing connections with new values:

bash
# Update an azure OpenAI connection with a new api base
pf connection update -n my_azure_open_ai_connection --set api_base='new_value'
# Update a custom connection
pf connection update -n my_custom_connection --set configs.other_config='new_value'

:::

:::{tab-item} SDK
:sync: SDK
The code snippet below shows how to update existing connections with new values:

python
# Update an azure OpenAI connection with a new api base
connection = pf.connections.get(name="my_azure_open_ai_connection")
connection.api_base = "new_value"
connection.api_key = "<original-key>"  # secrets are required when updating connection using sdk
result = pf.connections.create_or_update(connection)
print(connection)
# Update a custom connection
connection = pf.connections.get(name="my_custom_connection")
connection.configs["other_config"] = "new_value"
connection.secrets = {"key1": "val1"}  # secrets are required when updating connection using sdk
result = pf.connections.create_or_update(connection)
print(connection)

:::

:::{tab-item} VS Code Extension
:sync: VSC

On the VS Code primary sidebar > prompt flow pane. You can find the connections pane to manage your local connections. Right click the item of the connection list to update or delete your connections.

:::
::::

List connections

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
List connection command will return the connections with json list format, note that all secrets and api keys will be scrubbed:

bash
pf connection list

:::

:::{tab-item} SDK
:sync: SDK
List connection command will return the connections object list, note that all secrets and api keys will be scrubbed:

python
from promptflow.client import PFClient
# Get a pf client to manage connections
pf = PFClient()
# List and print connections
connection_list = pf.connections.list()
for connection in connection_list:
    print(connection)

:::

:::{tab-item} VS Code Extension
:sync: VSC

:::
::::

Delete a connection

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
Delete a connection with the following command:

bash
pf connection delete -n <connection_name>

:::

:::{tab-item} SDK
:sync: SDK
Delete a connection with the following code snippet:

python
from promptflow.client import PFClient

# Get a pf client to manage connections
pf = PFClient()
# Delete the connection with specific name
pf.connections.delete(name="my_custom_connection")

:::

:::{tab-item} VS Code Extension
:sync: VSC

On the VS Code primary sidebar > prompt flow pane. You can find the connections pane to manage your local connections. Right click the item of the connection list to update or delete your connections.

:::
::::

Load from environment variables

With promptflow>=1.8.0, user is able to load a connection object from os environment variables with <ConnectionType>.from_env func.
Note that the connection object will NOT BE CREATED to local database.

Supported types are as follows:

Connection Type Field Relevant Environment Variable
OpenAIConnection api_key OPENAI_API_KEY
organization OPENAI_ORG_ID
base_url OPENAI_BASE_URL
AzureOpenAIConnection api_key AZURE_OPENAI_API_KEY
api_base AZURE_OPENAI_ENDPOINT
api_version OPENAI_API_VERSION

For example, with OPENAI_API_KEY set to environment, an OpenAIConnection object can be loaded with OpenAIConnection.from_env().

Authenticate with Microsoft Entra ID

Microsoft Entra ID is a cloud-based identity and access management service that enables your employees access external resources.

Some promptflow connection types supports connection authentication with Microsoft Entra ID.

Connection Type Yaml Field Value Package Requirements VS Code Extension
AzureOpenAIConnection auth_mode meid_token promptflow[azureml-serving]>=1.7.0, promptflow-tools>=1.4.0 1.20.0

Next steps


How To Guides Quick Start (`docs/how-to-guides/quick-start.md`)

Quick start

This guide will walk you through the first steps of the prompt flow code-first experience.

Prerequisite - To make the most of this tutorial, you'll need:

  • Python programming knowledge

Learning Objectives - Upon completing this tutorial, you should know how to:

  • Setup your python environment to run prompt flow
  • Create a flow using a prompt and python function
  • Test the flow using your favorite experience: CLI, SDK or UI.

Installation

Install promptflow package to start.

sh
pip install promptflow

Learn more about installation.

Create your first flow

Model a LLM call with a prompty

Create a Prompty file to help you trigger one LLM call.

md
---
name: Minimal Chat
model:
  api: chat
  configuration:
    type: azure_openai
    azure_deployment: gpt-35-turbo
  parameters:
    temperature: 0.2
    max_tokens: 1024
inputs:
  question:
    type: string
sample:
  question: "What is Prompt flow?"
---

system:
You are a helpful assistant.

user:
{{question}}

Prompty is a markdown file. The front matter structured in YAML, encapsulates a series of metadata fields pivotal for defining the model’s configuration and the inputs for the prompty. After this front matter is the prompt template, articulated in the Jinja format.
See more details in Develop a prompty.

Create a flow

Create a python function which is the entry of a flow.

python
import os

from dotenv import load_dotenv
from pathlib import Path
from promptflow.tracing import trace
from promptflow.core import Prompty

BASE_DIR = Path(__file__).absolute().parent

@trace
def chat(question: str = "What's the capital of France?") -> str:
    """Flow entry function."""

    if "OPENAI_API_KEY" not in os.environ and "AZURE_OPENAI_API_KEY" not in os.environ:
        # load environment variables from .env file
        load_dotenv()

    prompty = Prompty.load(source=BASE_DIR / "chat.prompty")
    # trigger a llm call with the prompty obj
    output = prompty(question=question)
    return output

Flow can be a python function or class or a yaml file describing a DAG which encapsulates your LLM application logic.
Learn more on the flow concept and how to Develop a flow.

See the full example of this python file in: Minimal Chat.

Test the flow

Test the flow with your favorite experience: CLI, SDK or UI.

::::{tab-set}

:::{tab-item} CLI
:sync: CLI

pf is the CLI command you get when you install the promptflow package. Learn more about features of the pf CLI in the reference doc.

sh
pf flow test --flow flow:chat --inputs question="What's the capital of France?"

You will get some output like the following in your terminal.

text
Prompt flow service has started...
You can view the trace detail from the following URL:
http://127.0.0.1:51330/v1.0/ui/traces/?#collection=chat-minimal&uiTraceId=0x49382bbe30664f747348a8ae9dc8b954

The capital of France is Paris

If you click the trace URL printed, you will see a trace UI which helps you understand the actual LLM call that happened behind the scenes.

:::

:::{tab-item} SDK
:sync: SDK

Call the chat function with your question. Assume you have a flow.py file with the following content.

python
if __name__ == "__main__":
    from promptflow.tracing import start_trace

    start_trace()

    result = chat("What's the capital of France?")
    print(result)

Run the script with python flow.py, and you will get some output like below:

text
Prompt flow service has started...
You can view the trace detail from the following URL:
http://127.0.0.1:51330/v1.0/ui/traces/?#collection=chat-minimal&uiTraceId=0x49382bbe30664f747348a8ae9dc8b954

The capital of France is Paris

If you click the trace URL printed, you will see a trace UI which helps you understand the actual LLM call that happened behind the scenes.

:::

:::{tab-item} UI
:sync: VS Code Extension

Start test chat ui with below command.

sh
pf flow test --flow flow:chat --ui

The command will open a browser page like below:

See more details of this topic in Chat with a flow.

Click the "View trace" button to see a trace UI which helps you understand the actual LLM call that happened behind the scenes.

:::

::::

Next steps

Learn more on how to:

And you can also check our Tutorials, especially:

  • Tutorial: Chat with PDF: An end-to-end tutorial on how to build a high quality chat application with prompt flow, including flow development and evaluation with metrics.

How To Guides Set Promptflow Configs (`docs/how-to-guides/set-promptflow-configs.md`)

Set promptflow configs

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Promptflow supports setting global configs to avoid passing the same parameters to each command. The global configs are stored in a yaml file, which is located at ~/.promptflow/pf.yaml by default.

Additionally, promptflow supports setting configs to a specified path, and these configs will only take effect for the Promptflow program when the working directory is the specified path or its subdirectories.
The configs are stored in a yaml file, which is located at <config_folder>/pf.yaml.

The config file is shared between promptflow extension and sdk/cli. Promptflow extension controls each config through UI, so the following sections will show how to set global configs using promptflow cli.

Set config

Set global config

shell
pf config set <config_name>=<config_value>

For example:

shell
pf config set connection.provider="azureml://subscriptions/<your-subscription>/resourceGroups/<your-resourcegroup>/providers/Microsoft.MachineLearningServices/workspaces/<your-workspace>"

Setting the config for a specific path

shell
pf config set <config_name>=<config_value> --path <config_folder>

For example:

shell
pf config set connection.provider="azureml://subscriptions/<your-subscription>/resourceGroups/<your-resourcegroup>/providers/Microsoft.MachineLearningServices/workspaces/<your-workspace>" --path .

Show config

The following command will get all configs and show them as json format:

shell
pf config show

After running the above config set command, show command will return the following result:

json
{
  "connection": {
    "provider": "azureml://subscriptions/<your-subscription>/resourceGroups/<your-resourcegroup>/providers/Microsoft.MachineLearningServices/workspaces/<your-workspace>"
  }
}

Supported configs

connection.provider

The connection provider, default to "local". There are 3 possible provider values.

local

Set connection provider to local with connection.provider=local.

Connections will be saved locally. PFClient(or pf connection commands) will manage local connections. Consequently, the flow will be executed using these local connections.

full azure machine learning workspace resource id

Set connection provider to a specific workspace with:

text
connection.provider=azureml://subscriptions/<your-subscription>/resourceGroups/<your-resourcegroup>/providers/Microsoft.MachineLearningServices/workspaces/<your-workspace>

When get or list connections, PFClient(or pf connection commands) will return workspace connections, and flow will be executed using these workspace connections.
Secrets for workspace connection will not be shown by those commands, which means you may see empty dict {} for custom connections.

:::{note}
Command create, update and delete are not supported for workspace connections, please manage it in workspace portal, Azure AI Studio, az ml cli or azure-ai-ml sdk.
:::

azureml

In addition to the full resource id, you can designate the connection provider as "azureml" with connection.provider=azureml. In this case,
promptflow will attempt to retrieve the workspace configuration by searching .azureml/config.json from the current directory, then progressively from its parent folders. So it's possible to set the workspace configuration for different flow by placing the config file in the project folder.

The expected format of the config file is as follows:

json
{
  "workspace_name": "<your-workspace-name>",
  "resource_group": "<your-resource-group>",
  "subscription_id": "<your-subscription-id>"
}

service.host

The promptflow service host, default to "127.0.0.1". You can set the service host with service.host=<your-host>.

For example:

shell
pf config set service.host="0.0.0.0"

πŸ’‘ Tips
In addition to the CLI command line setting approach, we also support setting this connection provider through the VS Code extension UI. Click here to learn more.


How To Guides Tune Prompts With Variants (`docs/how-to-guides/tune-prompts-with-variants.md`)

Tune prompts using variants

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

To better understand this part, please read Quick start and Run and evaluate a flow first.

What is variant and why should we care

In order to help users tune the prompts in a more efficient way, we introduce the concept of variants which can help you test the model’s behavior under different conditions, such as different wording, formatting, context, temperature, or top-k, compare and find the best prompt and configuration that maximizes the model’s accuracy, diversity, or coherence.

Create a run with different variant node

In this example, we use the flow web-classification, its node summarize_text_content has two variants: variant_0 and variant_1. The difference between them is the inputs parameters:

yaml
...
nodes:
- name: summarize_text_content
  use_variants: true
...
node_variants:
  summarize_text_content:
    default_variant_id: variant_0
    variants:
      variant_0:
        node:
          type: llm
          source:
            type: code
            path: summarize_text_content.jinja2
          inputs:
            deployment_name: text-davinci-003
            max_tokens: '128'
            temperature: '0.2'
            text: ${fetch_text_content_from_url.output}
          provider: AzureOpenAI
          connection: open_ai_connection
          api: completion
          module: promptflow.tools.aoai
      variant_1:
        node:
          type: llm
          source:
            type: code
            path: summarize_text_content__variant_1.jinja2
          inputs:
            deployment_name: text-davinci-003
            max_tokens: '256'
            temperature: '0.3'
            text: ${fetch_text_content_from_url.output}
          provider: AzureOpenAI
          connection: open_ai_connection
          api: completion
          module: promptflow.tools.aoai

You can check the whole flow definition in flow.dag.yaml.

Now we will create a variant run which uses node summarize_text_content's variant variant_1.
Assuming you are in working directory /examples/flows/standard

::::{tab-set}

:::{tab-item} CLI
:sync: CLI

Note we pass --variant to specify which variant of the node should be running.

sh
pf run create --flow web-classification --data web-classification/data.jsonl --variant '${summarize_text_content.variant_1}' --column-mapping url='${data.url}' --stream --name my_first_variant_run

:::

:::{tab-item} SDK
:sync: SDK

python
from promptflow.client import PFClient

pf = PFClient()  # get a promptflow client
flow = "web-classification"
data= "web-classification/data.jsonl"

# use the variant1 of the summarize_text_content node.
variant_run = pf.run(
    flow=flow,
    data=data,
    variant="${summarize_text_content.variant_1}",  # use variant 1.
    column_mapping={"url": "${data.url}"},
)

pf.stream(variant_run)

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

:::

::::

After the variant run is created, you can evaluate the variant run with a evaluation flow, just like you evalute a standard flow run.

Next steps

Learn more about:


Reference Flow Yaml Schema Reference (`docs/reference/flow-yaml-schema-reference.md`)

Flow YAML Schema

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

The source JSON schema can be found at Flow.schema.json

YAML syntax

Key Type Description
$schema string The YAML schema. If you use the prompt flow VS Code extension to author the YAML file, including $schema at the top of your file enables you to invoke schema and resource completions.
inputs object Dictionary of flow inputs. The key is a name for the input within the context of the flow and the value is the flow input definition.
inputs. object The flow input definition. See Flow input for the set of configurable properties.
outputs object Dictionary of flow outputs. The key is a name for the output within the context of the flow and the value is the flow output definition.
outputs.<output_name> object The component output definition. See Flow output for the set of configurable properties.
nodes array Sets of dictionary of individual nodes to run as steps within the flow. Node can use built-in tool or third-party tool. See Nodes for more information.
node_variants object Dictionary of nodes with variants. The key is the node name and value contains variants definition and default_variant_id. See Node variants for more information.
environment object The environment to use for the flow. The key can be image or python_requirements_txt and the value can be either a image or a python requirements text file.
environment_variables object/string Environment variables to set by specifying a property path and value. Example: {"key1"="${my_connection.api_key}"}. The value reference to connection keys will be resolved to the actual value, and all environment variables specified will be set into os.environ.
additional_includes array Additional includes is a list of files that can be shared among flows. Users can specify additional files and folders used by flow, and prompt flow will help copy them all to the snapshot during flow creation.

Flow input

Key Type Description Allowed values
type string The type of flow input. int, double, bool, string, list, object, image
description string Description of the input.
default int, double, bool, string, list, object, image The default value for the input.
is_chat_input boolean Whether the input is the chat flow input.
is_chat_history boolean Whether the input is the chat history for chat flow.

Flow output

Key Type Description Allowed values
type string The type of flow output. int, double, bool, string, list, object
description string Description of the output.
reference string A reference to the node output, e.g. ${.output.}
is_chat_output boolean Whether the output is the chat flow output.

Nodes

Nodes is a set of node which is a dictionary with following fields. Below, we only show the common fields of a single node using built-in tool.

Key Type Description Allowed values
name string The name of the node.
type string The type of the node. Type of built-in tool like Python, Prompt, LLM and third-party tool like Vector Search, etc.
inputs object Dictionary of node inputs. The key is the input name and the value can be primitive value or a reference to the flow input or the node output, e.g. ${inputs.<flow_input_name>}, ${<node_name>.output} or ${<node_name>.output.<node_output_name>}
source object Dictionary of tool source used by the node. The key contains type, path and tool. The type can be code, package and package_with_prompt.
provider string It indicates the provider of the tool. Used when the type is LLM. AzureOpenAI or OpenAI
connection string The connection name which has been created before. Used when the type is LLM.
api string The api name of the provider. Used when the type is LLM.
module string The module name of the tool using by the node. Used when the type is LLM.
use_variants bool Whether the node has variants.

Node variants

Node variants is a dictionary containing variants definition for nodes with variants with their respective node names as dictionary keys.
Below, we explore the variants for a single node.

Key Type Description Allowed values
<node_name> string The name of the node.
default_variant_id string Default variant id.
variants object This dictionary contains all node variations, with the variant id serving as the key and a node definition dictionary as the corresponding value. Within the node definition dictionary, the key labeled 'node' should contain a variant definition similar to Nodes, excluding the 'name' field.

Examples

Flow examples are available in the GitHub repository.


Reference Pf Command Reference (`docs/reference/pf-command-reference.md`)

pf

Manage prompt flow resources with the prompt flow CLI.

Command Description
pf flow Manage flows.
pf connection Manage connections.
pf run Manage runs.
pf tool Init or list tools.
pf config Manage config for current user.
pf service Manage prompt flow service.
pf upgrade Upgrade prompt flow CLI.
pf trace Manage traces.

pf flow

Manage promptflow flow flows.

Command Description
pf flow init Initialize a prompt flow directory.
pf flow test Test the prompt flow or flow node.
pf flow validate Validate a flow and generate flow.tools.json for it.
pf flow build Build a flow for further sharing or deployment.
pf flow serve Serve a flow as an endpoint.

pf flow init

Initialize a prompt flow directory.

bash
pf flow init [--flow]
             [--entry]
             [--function]
             [--prompt-template]
             [--type]
             [--yes]

Examples

Create a flow folder with code, prompts and YAML specification of the flow.

bash
pf flow init --flow <path-to-flow-direcotry>

Create an evaluation prompt flow

bash
pf flow init --flow <path-to-flow-direcotry> --type evaluation

Create a flow in existing folder

bash
pf flow init --flow <path-to-existing-folder> --entry <entry.py> --function <function-name> --prompt-template <path-to-prompt-template.md>

Optional Parameters

--flow

The flow name to create.

--entry

The entry file name.

--function

The function name in entry file.

--prompt-template

The prompt template parameter and assignment.

--type

The initialized flow type.
accepted value: standard, evaluation, chat

--yes --assume-yes -y

Automatic yes to all prompts; assume 'yes' as answer to all prompts and run non-interactively.

pf flow test

Test the prompt flow or flow node.

bash
pf flow test --flow
             [--inputs]
             [--node]
             [--variant]
             [--debug]
             [--interactive]
             [--verbose]
             [--ui]
             [--collection]

Examples

Test the flow.

bash
pf flow test --flow <path-to-flow-directory>

Test the flow from json file.

bash
pf flow test --flow <path-to-flow-directory> --inputs inputs.json

Test the flow with first line from jsonl file.

bash
pf flow test --flow <path-to-flow-directory> --inputs inputs.jsonl

Test the flow with input values.

bash
pf flow test --flow <path-to-flow-directory> --inputs data_key1=data_val1 data_key2=data_val2

Test the flow with specified variant node.

bash
pf flow test --flow <path-to-flow-directory> --variant '${node_name.variant_name}'

Test the single node in the flow.

bash
pf flow test --flow <path-to-flow-directory> --node <node_name>

Debug the single node in the flow.

bash
pf flow test --flow <path-to-flow-directory> --node <node_name> --debug

Chat in the flow.

bash
pf flow test --flow <path-to-flow-directory> --node <node_name> --interactive

Chat in the chat window.

bash
pf flow test --flow <path-to-flow-directory> --ui

Test the flow while log traces to a specific collection.

bash
pf flow test --flow <path-to-flow-directory> --collection <collection>

Required Parameter

--flow

The flow directory to test.

Optional Parameters

--inputs

Input data for the flow. Example: --inputs data1=data1_val data2=data2_val

--node

The node name in the flow need to be tested.

--variant

Node & variant name in format of ${node_name.variant_name}.

--debug

Debug the single node in the flow.

--interactive

Start a interactive chat session for chat flow.

--verbose

Displays the output for each step in the chat flow.

--ui

The flag to start an interactive chat experience in local chat window.

pf flow validate

Validate the prompt flow and generate a flow.tools.json under .promptflow. This file is required when using flow as a component in a Azure ML pipeline.

bash
pf flow validate --source
                 [--debug]
                 [--verbose]

Examples

Validate the flow.

bash
pf flow validate --source <path-to-flow>

Required Parameter

--source

The flow source to validate.

pf flow build

Build a flow for further sharing or deployment.

bash
pf flow build --source
              --output
              --format
              [--variant]
              [--verbose]
              [--debug]

Examples

Build a flow as docker, which can be built into Docker image via docker build.

bash
pf flow build --source <path-to-flow> --output <output-path> --format docker

Build a flow as docker with specific variant.

bash
pf flow build --source <path-to-flow> --output <output-path> --format docker --variant '${node_name.variant_name}'

Required Parameter

--source

The flow or run source to be used.

--output

The folder to output built flow. Need to be empty or not existed.

--format

The format to build flow into

Optional Parameters

--variant

Node & variant name in format of ${node_name.variant_name}.

--verbose

Show more details for each step during build.

--debug

Show debug information during build.

pf flow serve

Serving a flow as an endpoint.

bash
pf flow serve --source
              [--port]
              [--host]
              [--environment-variables]
              [--verbose]
              [--debug]
              [--skip-open-browser]
              [--engine]

Examples

Serve flow as an endpoint.

bash
pf flow serve --source <path-to-flow>

Serve flow as an endpoint with specific port and host.

bash
pf flow serve --source <path-to-flow> --port <port> --host <host> --environment-variables key1="`${my_connection.api_key}`" key2="value2"

Serve flow as an endpoint with specific port, host, environment-variables and fastapi serving engine.

bash
pf flow serve --source <path-to-flow> --port <port> --host <host> --environment-variables key1="`${my_connection.api_key}`" key2="value2" --engine fastapi

Required Parameter

--source

The flow or run source to be used.

Optional Parameters

--port

The port on which endpoint to run.

--host

The host of endpoint.

--environment-variables

Environment variables to set by specifying a property path and value. Example: --environment-variable key1="`${my_connection.api_key}`" key2="value2". The value reference to connection keys will be resolved to the actual value, and all environment variables specified will be set into os.environ.

--verbose

Show more details for each step during serve.

--debug

Show debug information during serve.

--skip-open-browser

Skip opening browser after serve. Store true parameter.

--engine

Switch python serving engine between flask amd fastapi, default to flask.

pf connection

Manage prompt flow connections.

Command Description
pf connection create Create a connection.
pf connection update Update a connection.
pf connection show Show details of a connection.
pf connection list List all the connection.
pf connection delete Delete a connection.

pf connection create

Create a connection.

bash
pf connection create --file
                     [--name]
                     [--set]

Examples

Create a connection with YAML file.

bash
pf connection create -f <yaml-filename>

Create a connection with YAML file with override.

bash
pf connection create -f <yaml-filename> --set api_key="<api-key>"

Create a custom connection with .env file; note that overrides specified by --set will be ignored.

bash
pf connection create -f .env --name <name>

Required Parameter

--file -f

Local path to the YAML file containing the prompt flow connection specification.

Optional Parameters

--name -n

Name of the connection.

--set

Update an object by specifying a property path and value to set. Example: --set property1.property2=.

pf connection update

Update a connection.

bash
pf connection update --name
                     [--set]

Example

Update a connection.

bash
pf connection update -n <name> --set api_key="<api-key>"

Required Parameter

--name -n

Name of the connection.

Optional Parameter

--set

Update an object by specifying a property path and value to set. Example: --set property1.property2=.

pf connection show

Show details of a connection.

bash
pf connection show --name

Required Parameter

--name -n

Name of the connection.

pf connection list

List all the connection.

bash
pf connection list

pf connection delete

Delete a connection.

bash
pf connection delete --name

Required Parameter

--name -n

Name of the connection.

pf run

Manage prompt flow runs.

Command Description
pf run create Create a run.
pf run update Update a run metadata, including display name, description and tags.
pf run stream Stream run logs to the console.
pf run list List runs.
pf run show Show details for a run.
pf run show-details Preview a run's intput(s) and output(s).
pf run show-metrics Print run metrics to the console.
pf run visualize Visualize a run.
pf run archive Archive a run.
pf run restore Restore an archived run.

pf run create

Create a run.

bash
pf run create [--file]
              [--flow]
              [--data]
              [--column-mapping]
              [--run]
              [--variant]
              [--stream]
              [--environment-variables]
              [--connections]
              [--set]
              [--source]
              [--resume-from] # require promptflow>=1.8.0, and original run created with promptflow>=1.8.0

Examples

Create a run with YAML file.

bash
pf run create -f <yaml-filename>

Create a run with YAML file and replace another data in the YAML file.

bash
pf run create -f <yaml-filename> --data <path-to-new-data-file-relative-to-yaml-file>

Create a run from flow directory and reference a run.

bash
pf run create --flow <path-to-flow-directory> --data <path-to-data-file> --column-mapping groundtruth='${data.answer}' prediction='${run.outputs.category}' --run <run-name> --variant '${summarize_text_content.variant_0}' --stream

Create a run from an existing run record folder.

bash
pf run create --source <path-to-run-folder>

Create a run by specifying the resume_from. (Require promptflow>=1.8.0, and original run created with promptflow>=1.8.0)

Succeeded line result of the original run will be reused, only remaining/failed lines will be run.

bash
pf run create --resume-from <original-run-name>
bash
pf run create --resume-from <original-run-name> --name <new-run-name> --set display_name='A new run' description='my run description' tags.Type=Test

Optional Parameters

--file -f

Local path to the YAML file containing the prompt flow run specification; can be overwritten by other parameters. Reference here for YAML schema.

--flow

Local path to the flow directory. If --file is provided, this path should be relative path to the file.

--data

Local path to the data file. If --file is provided, this path should be relative path to the file.

--column-mapping

Inputs column mapping, use ${data.xx} to refer to data columns, use ${run.inputs.xx} to refer to referenced run's data columns, and ${run.outputs.xx} to refer to run outputs columns.

--run

Referenced flow run name. For example, you can run an evaluation flow against an existing run. For example, "pf run create --flow evaluation_flow_dir --run existing_bulk_run".

--variant

Node & variant name in format of ${node_name.variant_name}.

--stream -s

Indicates whether to stream the run's logs to the console.
default value: False

--environment-variables

Environment variables to set by specifying a property path and value. Example:
--environment-variable key1='${my_connection.api_key}' key2='value2'. The value reference
to connection keys will be resolved to the actual value, and all environment variables
specified will be set into os.environ.

--connections

Overwrite node level connections with provided value.
Example: --connections node1.connection=test_llm_connection node1.deployment_name=gpt-35-turbo

--set

Update an object by specifying a property path and value to set.
Example: --set property1.property2=<value>.

--source

Local path to the existing run record folder.

pf run update

Update a run metadata, including display name, description and tags.

bash
pf run update --name
              [--set]

Example

Update a run

bash
pf run update -n <name> --set display_name="<display-name>" description="<description>" tags.key="value"

Required Parameter

--name -n

Name of the run.

Optional Parameter

--set

Update an object by specifying a property path and value to set. Example: --set property1.property2=.

pf run stream

Stream run logs to the console.

bash
pf run stream --name

Required Parameter

--name -n

Name of the run.

pf run list

List runs.

bash
pf run list [--all-results]
            [--archived-only]
            [--include-archived]
            [--max-results]

Optional Parameters

--all-results

Returns all results.
default value: False

--archived-only

List archived runs only.
default value: False

--include-archived

List archived runs and active runs.
default value: False

--max-results -r

Max number of results to return. Default is 50.
default value: 50

pf run show

Show details for a run.

bash
pf run show --name

Required Parameter

--name -n

Name of the run.

pf run show-details

Preview a run's input(s) and output(s).

bash
pf run show-details --name

Required Parameter

--name -n

Name of the run.

pf run show-metrics

Print run metrics to the console.

bash
pf run show-metrics --name

Required Parameter

--name -n

Name of the run.

pf run visualize

Visualize a run in the browser.

bash
pf run visualize --names

Required Parameter

--names -n

Name of the runs, comma separated.

pf run archive

Archive a run.

bash
pf run archive --name

Required Parameter

--name -n

Name of the run.

pf run restore

Restore an archived run.

bash
pf run restore --name

Required Parameter

--name -n

Name of the run.

pf tool

Manage promptflow tools.

Command Description
pf tool init Initialize a tool directory.
pf tool list List all tools in the environment.
pf tool validate Validate tools.

pf tool init

Initialize a tool directory.

bash
pf tool init [--package]
             [--tool]
             [--set]

Examples

Creating a package tool from scratch.

bash
pf tool init --package <package-name> --tool <tool-name>

Creating a package tool with extra info.

bash
pf tool init --package <package-name> --tool <tool-name> --set icon=<icon-path> category=<tool-category> tags="{'<key>': '<value>'}"

Creating a package tool from scratch.

bash
pf tool init --package <package-name> --tool <tool-name>

Creating a python tool from scratch.

bash
pf tool init --tool <tool-name>

Optional Parameters

--package

The package name to create.

--tool

The tool name to create.

--set

Set extra information about the tool, like category, icon and tags. Example: --set =.

pf tool list

List all tools in the environment.

bash
pf tool list [--flow]

Examples

List all package tool in the environment.

bash
pf tool list

List all package tool and code tool in the flow.

bash
pf tool list --flow <path-to-flow-direcotry>

Optional Parameters

--flow

The flow directory.

pf tool validate

Validate tool.

bash
pf tool validate --source

Examples

Validate single function tool.

bash
pf tool validate -–source <package-name>.<module-name>.<tool-function>

Validate all tool in a package tool.

bash
pf tool validate -–source <package-name>

Validate tools in a python script.

bash
pf tool validate --source <path-to-tool-script>

Required Parameter

--source

The tool source to be used.

pf config

Manage config for current user.

Command Description
pf config set Set prompt flow configs for current user.
pf config show Show prompt flow configs for current user.

pf config set

Set prompt flow configs for current user, configs will be stored at ~/.promptflow/pf.yaml.

bash
pf config set

Examples

Connection provider

Set connection provider to Azure ML workspace or Azure AI project for current user.

bash
pf config set connection.provider="azureml://subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.MachineLearningServices/workspaces/<workspace-or-project-name>"

Tracing

Set trace destination to Azure ML workspace or Azure AI project.

bash
pf config set trace.destination="azureml://subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.MachineLearningServices/workspaces/<workspace-or-project-name>"

Only log traces to local.

bash
pf config set trace.destination="local"

Disable tracing feature.

bash
pf config set trace.destination="none"

pf config show

Show prompt flow configs for current user.

bash
pf config show

Examples

Show prompt flow for current user.

bash
pf config show

pf service

Manage prompt flow service.

Command Description
pf service start Start prompt flow service.
pf service stop Stop prompt flow service.
pf service status Display the started prompt flow service info.

pf service start

Start the prompt flow service.

bash
pf service start [--port]
                 [--force]
                 [--debug]

Examples

Prompt flow will try to start the service on the default port 23333. If the port is already taken, prompt flow will
sequentially probe new ports, incrementing by one each time. Prompt flow retains the port number for future reference
and will utilize it for subsequent service startups.

bash
pf service start

Forcefully start the prompt flow service. If the port is already in use, the existing service will be terminated and
restart a new service

bash
pf service start --force

Start the prompt flow service with a specified port. If the port is already taken, prompt flow will raise an error
unless forcefully start the service with the --force flag. Upon availability, prompt flow retains the port number for
future reference and will utilize it for subsequent service startups.

bash
pf service start --port 65553

Start prompt flow service in foreground, displaying debug level logs directly in the terminal.

bash
pf service start --debug

Optional Parameters

--port -p

The designated port of the prompt flow service and port number will be remembered if port is available.

--force

Force restart the existing service if the port is used.

--debug

Start prompt flow service in foreground, displaying debug level logs directly in the terminal.

pf service stop

Stop prompt flow service.

bash
pf service stop [--debug]

Example

Stop prompt flow service.

bash
pf service stop

Optional Parameter

--debug

The flag to turn on debug mode for cli.

pf service status

Display the started prompt flow service info.

bash
pf service status

pf upgrade

Upgrade prompt flow CLI.

Command Description
pf upgrade Upgrade prompt flow CLI.

Examples

Upgrade prompt flow without prompt and run non-interactively.

bash
pf upgrade --yes

pf trace

Manage prompt flow traces.

Command Description
pf trace delete Delete traces

pf trace delete

Delete traces.

bash
pf trace delete [--run]
                [--collection]
                [--started-before]  # should combine with `collection`

Examples

Delete traces comes from a specific run.

bash
pf trace delete --run <run-name>

Delete traces in a specific collection.

bash
pf trace delete --collection <collection>

Delete traces in a specific collection started before a specific time.

bash
# `started-before` should be in ISO 8601 format
pf trace delete --collection <collection> --started-before '2024-03-19T15:17:23.807563'

Autocomplete

To activate autocomplete features for the pf CLI you need to add the following snippet to your ~/.bashrc or ~/.zshrc:

bash
source <promptflow_package_install_root>/pf.completion.sh

Reference Pfazure Command Reference (`docs/reference/pfazure-command-reference.md`)

pfazure

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Manage prompt flow resources on Azure with the prompt flow CLI.

Command Description
pfazure flow Manage flows.
pfazure run Manage runs.

pfazure flow

Manage flows.

Command Description
pfazure flow create Create a flow.
pfazure flow update Update a flow.
pfazure flow list List flows in a workspace.

pfazure flow create

Create a flow in Azure AI from a local flow folder.

bash
pfazure flow create [--flow]
                    [--set]
                    [--subscription]
                    [--resource-group]
                    [--workspace-name]

Parameters

--flow

Local path to the flow directory.

--set

Update an object by specifying a property path and value to set.

  • display_name: Flow display name that will be created in remote. Default to be flow folder name + timestamp if not specified. e.g. "--set display_name=<display_name>".
  • type: Flow type. Default to be "standard" if not specified. Available types are: "standard", "evaluation", "chat". e.g. "--set type=<type>".
  • description: Flow description. e.g. "--set description=<description>."
  • tags: Flow tags. e.g. "--set tags.key1=value1 tags.key2=value2."

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure flow update

Update a flow's metadata, such as display name, description and tags.

bash
pfazure flow update --flow
                    [--set]
                    [--subscription]
                    [--resource-group]
                    [--workspace-name]

Parameters

--flow

The flow name on azure. It's a guid that can be found from 2 ways:

--set

Update an object by specifying a property path and value to set.

  • display_name: Flow display name. e.g. "--set display_name=<display_name>".
  • description: Flow description. e.g. "--set description=<description>."
  • tags: Flow tags. e.g. "--set tags.key1=value1 tags.key2=value2."

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure flow list

List remote flows on Azure AI.

bash
pfazure flow list [--max-results]
                  [--include-others]
                  [--type]
                  [--output]
                  [--archived-only]
                  [--include-archived]
                  [--subscription]
                  [--resource-group]
                  [--workspace-name]
                  [--output]

Parameters

--max-results -r

Max number of results to return. Default is 50, upper bound is 100.

--include-others

Include flows created by other owners. By default only flows created by the current user are returned.

--type

Filter flows by type. Available types are: "standard", "evaluation", "chat".

--archived-only

List archived flows only.

--include-archived

List archived flows and active flows.

--output -o

Output format. Allowed values: json, table. Default: json.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run

Manage prompt flow runs.

Command Description
pfazure run create Create a run.
pfazure run list List runs in a workspace.
pfazure run show Show details for a run.
pfazure run stream Stream run logs to the console.
pfazure run show-details Show a run details.
pfazure run show-metrics Show run metrics.
pfazure run visualize Visualize a run.
pfazure run archive Archive a run.
pfazure run restore Restore a run.
pfazure run update Update a run.
pfazure run download Download a run.

pfazure run create

Create a run.

bash
pfazure run create [--file]
                   [--flow]
                   [--data]
                   [--column-mapping]
                   [--run]
                   [--variant]
                   [--stream]
                   [--environment-variables]
                   [--connections]
                   [--resume-from] # require promptflow>=1.8.0
                   [--set]
                   [--subscription]
                   [--resource-group]
                   [--workspace-name]

Parameters

--file -f

Local path to the YAML file containing the prompt flow run specification; can be overwritten by other parameters. Reference here for YAML schema.

--flow

The flow source to create the run. It could be:

  • Local path to the flow directory.
    bash
    pfazure run create --flow <path-to-flow-directory> --data <path-to-data-file> --column-mapping <key-value-pair>
  • The flow name on azure with a prefix azureml:. Flow name is a guid that can be found from 2 ways:
    bash
    pfazure run create --flow azureml:<flow-name> --data <path-to-data-file> --column-mapping <key-value-pair>

--data

Local path to the data file or remote data. e.g. azureml:name:version.

--column-mapping

Inputs column mapping, use ${data.xx} to refer to data columns, use ${run.inputs.xx} to refer to referenced run's data columns, and ${run.outputs.xx} to refer to run outputs columns.

--run

Referenced flow run name. For example, you can run an evaluation flow against an existing run. For example, "pfazure run create --flow evaluation_flow_dir --run existing_bulk_run --column-mapping url='${data.url}'".

--variant

Node & variant name in format of ${node_name.variant_name}.

--stream -s

Indicates whether to stream the run's logs to the console.
default value: False

--environment-variables

Environment variables to set by specifying a property path and value. Example:
--environment-variable key1='${my_connection.api_key}' key2='value2'. The value reference
to connection keys will be resolved to the actual value, and all environment variables
specified will be set into os.environ.

--connections

Overwrite node level connections with provided value.
Example: --connections node1.connection=test_llm_connection node1.deployment_name=gpt-35-turbo

--resume-from

Create a run resume from an existing run. (Require promptflow>=1.8.0)
Example: --resume-from <run_name>

--set

Update an object by specifying a property path and value to set.
Example: --set property1.property2=<value>.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run list

List runs in a workspace.

bash
pfazure run list [--archived-only]
                 [--include-archived]
                 [--max-results]
                 [--subscription]
                 [--resource-group]
                 [--workspace-name]

Parameters

--archived-only

List archived runs only.
default value: False

--include-archived

List archived runs and active runs.
default value: False

--max-results -r

Max number of results to return. Default is 50, upper bound is 100.
default value: 50

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run show

Show details for a run.

bash
pfazure run show --name
                 [--subscription]
                 [--resource-group]
                 [--workspace-name]

Parameters

--name -n

Name of the run.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run stream

Stream run logs to the console.

bash
pfazure run stream --name
                   [--timeout]
                   [--subscription]
                   [--resource-group]
                   [--workspace-name]

Parameters

--name -n

Name of the run.

--timeout

Timeout in seconds. If the run stays in the same status and produce no new logs in a period longer than the timeout value, the stream operation will abort. Default value is 600 seconds

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run show-details

Show a run details.

bash
pfazure run show-details --name
                         [--subscription]
                         [--resource-group]
                         [--workspace-name]

Parameters

--name -n

Name of the run.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run show-metrics

Show run metrics.

bash
pfazure run show-metrics --name
                         [--subscription]
                         [--resource-group]
                         [--workspace-name]

Parameters

--name -n

Name of the run.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run visualize

Visualize a run.

bash
pfazure run visualize --name
                      [--subscription]
                      [--resource-group]
                      [--workspace-name]

Parameters

--name -n

Name of the run.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run archive

Archive a run.

bash
pfazure run archive --name
                    [--subscription]
                    [--resource-group]
                    [--workspace-name]

Parameters

--name -n

Name of the run.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run restore

Restore a run.

bash
pfazure run restore --name
                    [--subscription]
                    [--resource-group]
                    [--workspace-name]

Parameters

--name -n

Name of the run.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run update

Update a run's metadata, such as display name, description and tags.

bash
pfazure run update --name
                    [--set display_name="<value>" description="<value>" tags.key="<value>"]
                    [--subscription]
                    [--resource-group]
                    [--workspace-name]

Examples

Set display name, description and tags:

bash
pfazure run update --name <run_name> --set display_name="<value>" description="<value>" tags.key="<value>"

Parameters

--name -n

Name of the run.

--set

Set meta information of the run, like display_name, description or tags. Example: --set =.

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.

pfazure run download

Download a run's metadata, such as input, output, snapshot and artifact. After the download is finished, you can use pf run create --source <run-info-local-folder> to register this run as a local run record, then you can use commands like pf run show/visualize to inspect the run just like a run that was created from local flow.

bash
pfazure run download --name
                    [--output]
                    [--overwrite]
                    [--subscription]
                    [--resource-group]
                    [--workspace-name]

Examples

Download a run data to local:

bash
pfazure run download --name <name> --output <output-folder-path>

Parameters

--name -n

Name of the run.

--output -o

Output folder path to store the downloaded run data. Default to be ~/.promptflow/.runs if not specified

--overwrite

Overwrite the existing run data if the output folder already exists. Default to be False if not specified

--subscription

Subscription id, required when there is no default value from az configure.

--resource-group -g

Resource group name, required when there is no default value from az configure.

--workspace-name -w

Workspace name, required when there is no default value from az configure.


Reference Run Yaml Schema Reference (`docs/reference/run-yaml-schema-reference.md`)

Run YAML Schema

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

The source JSON schema can be found at Run.schema.json

YAML syntax

Key Type Description
$schema string The YAML schema. If you use the prompt flow VS Code extension to author the YAML file, including $schema at the top of your file enables you to invoke schema and resource completions.
name string The name of the run.
flow string Path of the flow directory.
description string Description of the run.
display_name string Display name of the run.
data string Input data for the run. Local path or remote uri(starts with azureml: or public URL) are supported. Note: remote uri is only supported for cloud run.
run string Referenced flow run name. For example, you can run an evaluation flow against an existing run.
column_mapping object Inputs column mapping, use ${data.xx} to refer to data columns, use ${run.inputs.xx} to refer to referenced run's data columns, and ${run.outputs.xx} to refer to run outputs columns.
connections object Overwrite node level connections with provided value. Example: --connections node1.connection=test_llm_connection node1.deployment_name=gpt-35-turbo
environment_variables object/string Environment variables to set by specifying a property path and value. Example: {"key1"="${my_connection.api_key}"}. The value reference to connection keys will be resolved to the actual value, and all environment variables specified will be set into os.environ.
properties object Dictionary of properties of the run.
tags object Dictionary of tags of the run.
resources object Dictionary of resources used for compute session. Only supported for cloud run. See Resources Schema for the set of configurable properties.
variant string The variant for the run.
status string The status of the run. Only available for when getting an existing run. Won't take affect if set when creating a run.
identity object Dictionary of identity configuration for compute session. Only supported for cloud run. See Identity Schema for the set of configurable properties.

Resources Schema

Key Type Description
instance_type string The instance type for compute session of the run.
compute string The compute instance for compute session session.

Identity Schema

Key Type Description
type string Identity type, currently only support managed and user_identity.
client_id string Client id for managed identity, only avaible on managed identity.

Examples

Run examples are available in the GitHub repository.

Run with identity examples

yaml
# default value
identity:
  type: user_identity

# use workspace primary UAI
identity:
  type: managed

# use specified client_id's UAI
identity:
  type: managed
  client_id: xxx

Reference Trace Span Spec Reference (`docs/reference/trace-span-spec-reference.md`)

Trace Span Specification

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

This document outlines the design of Prompt flow spans, detailing what information is traced and how it is structured.

Introduction

The span, as you may know, is the fundamental unit of the trace system, representing a unit that captures execution information in the Prompt flow system. Spans are nested together in a parent-child relationship and paired together by link relationships, providing developers and users with a comprehensive view of the application’s execution process.

By adhering to these specifications, we ensure transparency and consistency in our tracing system.

The UI interprets the captured spans and presents them in a user-friendly manner. Understanding the fields and contracts defined within the spans is essential for effectively utilizing Prompt flow or integrating its components.

OpenTelemetry Span Basics

A typical span object contains below information:

Field Description
name Name of span
parent_id Parent span ID (empty for root spans)
context Span Context
start_time Start time of the span
end_time End time of the span
status Span Status
attributes Attributes
events Span Events
links Span Links

Span in Prompt flow

In Prompt flow, we define several span types, and the system automatically creates spans with execution information in designated attributes and events.

These span types share common attributes and events, which we refer to as standard attributes and events. Let’s explore these common elements before diving into the specifics of each span type.

Common Attributes and Events

Attributes

Each span in Prompt flow is enriched with a set of standard attributes that provide essential information about the span's context and purpose. The following table outlines these attributes:

Attribute Type Description Examples Requirement Level
framework string This attribute specifies the framework in which the trace was recorded. For our project, this value is consistently set to promptflow. promptflow Required
node_name string Denotes the name of the flow node. chat Conditionally Required if the flow is a Directed Acyclic Graph (DAG) flow.
span_type string Specifies the type of span, such as LLM or Flow. See this for details. LLM Required
line_run_id string Unique identifier for the execution run within Prompt flow. d23159d5-cae0-4de6-a175-295c715ce251 Required
function string The function associated with the span. search Recommended
session_id string Unique identifier for chat sessions. 4ea1a462-7617-439f-a40c-12a8b93f51fb Opt-In
referenced.line_run_id string Represents the line run ID that is the source of the evaluation run. f747f7b8-983c-4bf2-95db-0ec3e33d4fd1 Conditionally Required only used in evaluation runs - runs on evaluation flow.
batch_run_id string The batch run ID when in batch mode. 61daff70-80d5-4e79-a50b-11b38bb3d344 Conditionally Required only used in batch runs.
referenced.batch_run_id string Notes the batch run ID against which an evaluation flow ran. 851b32cb-545c-421d-8e51-0a3ea66f0075 Conditionally Required only used in evaluation runs.
line_number int The line number within a batch run, starting from 0. 1 Conditionally Required only used in batch runs.
__computed__.cumulative_token_count.prompt int Cumulative token count of child nodes for prompts. [1] 200 Recommended
__computed__.cumulative_token_count.completion int Cumulative token count of child nodes for completion responses. [1] 80 Recommended
__computed__.cumulative_token_count.total int Total cumulative token count for both prompts and completions. [1] 120 Recommended

[1]: Cumulative token counts are propagated up the span hierarchy, ensuring each span reflects the total token count of all LLM executions within its scope.

Events

In Prompt flow, events emitted by the Prompt flow framework follow the format below

  • event MUST has attributes
  • event attributes MUST contain a key named payload, which refers to the data carried within an event.
  • event attributes payload MUST be a JSON string that represent an object.
Event Payload Description Payload Examples Requirement Level
promptflow.function.inputs Input of a function call {"chat_history":[],"question":"What is ChatGPT?"} Required
promptflow.function.output Output of a function call {"answer":"ChatGPT is a conversational AI model developed by OpenAI."} Required

Span Types Specification

Within the Prompt flow system, we have delineated several distinct span types to cater to various execution units. Each span type is designed to capture specific execution information, complementing the standard attributes and events. Currently, our system includes the following span types: LLM, Function, LangChain, Flow, Embedding and Retrieval.

Beyond the standard attributes and events, each span type possesses designated fields to store pertinent information unique to its role within the system. These specialized attributes and events ensure that all relevant data is meticulously traced and available for analysis.

LLM

The LLM (Large Language Model) span captures detailed execution information from calls to large language models.

Attribute Type Description Examples Requirement Level
span_type string Identifies the span as an LLM type. LLM Required
llm.usage.total_tokens int Total number of tokens used, including both prompt and response. 180 Required
llm.usage.prompt_tokens int Number of tokens used in the LLM prompt. 100 Required
llm.usage.completion_tokens int Number of tokens used in the LLM response (completion). 80 Required
llm.response.model string Specifies the LLM that generated the response. gpt-4 Required
Event Payload Description Payload Examples Requirement Level
promptflow.llm.generated_message Captures the output message from an LLM call. {"content":"ChatGPT is a conversational AI model developed by OpenAI.","role":"assistant","function_call":null,"tool_calls":null} Required

Note: OpenTelemetry currently defines several LLM-related span attributes and events as semantic conventions. We plan to align with these conventions in the future. For more information, visit Semantic Conventions for GenAI operations.

Function

The Function span is a versatile default span within Prompt flow, designed to capture a wide range of general function execution information.

Attribute Type Description Examples Requirement Level
span_type string Identifies the span as a Function type. Function Required
Event Payload Description Payload Examples Requirement Level
promptflow.prompt.template Details the prompt template and variable information. {"prompt.template":"# system:\nYou are a helpful assistant.\n\n# user:\n{{question}}","prompt.variables":"{\n "question": "What is ChatGPT?"\n}"} Conditionally Required if the function contains prompt template formating. [1]

[1]: Template formatting is a process by resolving prompt template into prompt message, this process can happen within a function that invokes LLM call.

Flow

The Flow span encapsulates the execution details of a flow within Prompt flow.

Attribute Type Description Examples Requirement Level
span_type string Designates the span as a Flow type. Flow Required

Embedding

The Embedding span is dedicated to recording the details of embedding calls within Prompt flow.

Attribute Type Description Examples Requirement Level
span_type string Denotes the span as an Embedding type. Embedding Required
llm.usage.total_tokens int Total number of tokens used, sum of prompt and response tokens. 180 Required
llm.usage.prompt_tokens int Number of tokens used in the prompt for the embedding call. 100 Required
llm.usage.completion_tokens int Number of tokens used in the response from the embedding call. 80 Required
llm.response.model string Identifies the LLM model used for generating the embedding. text-embedding-ada-002 Required
Event Payload Description Payload Examples Requirement Level
promptflow.embedding.embeddings Details the embeddings generated by a call. [{"embedding.vector":"","embedding.text":"When does a pipeline job reuse a previous job's results in Azure Machine Learning?"}] Required

Retrieval

The Retrieval span type is specifically designed to encapsulate the execution details of a retrieval task within Prompt flow.

Attribute Type Description Examples Requirement Level
span_type string Labels the span as a Retrieval type. Retrieval Required
Event Payload Description Payload Examples Requirement Level
promptflow.retrieval.query Captures the text of the retrieval query. "When does a pipeline job reuse a previous job's results in Azure Machine Learning?" Required
promptflow.retrieval.documents Details the list of retrieved documents relevant to the query. [{"document.id":"https://componentsdk.azurewebsites.net/howto/caching-reuse.html","document.score":2.677619457244873,"document.content":"# Component concepts &..."},{"document.id":"https://learn.microsoft.com/en-us/azure/machine-learning/v1/reference-pipeline-yaml","document.score":2.563112735748291,"document.content":"etc. |\r\n| runconfig | T..."}] Required

Cloud Azureai Consume Connections From Azure Ai (`docs/cloud/azureai/consume-connections-from-azure-ai.md`)

Consume connections from Azure AI

For a smooth development flow that transitions from cloud (Azure AI) to local environments, you can directly utilize the connection already established on the cloud by setting the connection provider to "Azure AI connections".

:::{note}
Promptflow is not able to manage connections from Azure AI, please manage it in workspace portal, Azure AI Studio, az ml cli or azure-ai-ml sdk.
:::

You can set the connection provider using the following steps:

  1. Navigate to the connection list in the VS Code primary sidebar.

  2. Click on the ... (more options icon) at the top and select the Set connection provider option.

  3. Choose one of the "Azure AI connections" provider types that you wish to use. Click to learn more about the differences between the connection providers.

    1. If you choose "Azure AI Connections - for current working directory", then you need to specify the cloud resources in the config.json file within the project folder.

    2. If you choose "Azure AI Connections - for this machine", specify the cloud resources in the connection string. You can do this in one of two ways:

      (1) Input connection string in the input box above.
      For example azureml://subscriptions/<your-subscription>/resourceGroups/<your-resourcegroup>/providers/Microsoft.MachineLearningServices/workspaces/<your-workspace>

      (2) Follow the wizard to set up your config step by step.

  4. Once the connection provider is set, the connection list will automatically refresh, displaying the connections retrieved from the selected provider.

Note:

  1. You need to have a project folder open to use the "Azure AI connections - for current working directory" option.
  2. Once you change the connection provider, it will stay that way until you change it again and save the new setting.

Different connection providers

Currently, we support three types of connections:

Connection provider Type Description Provider Specification Use Case
Local Connections Local Enables consume the connections created and locally and stored in local sqlite. NA Ideal when connections need to be stored and managed locally.
Azure AI connection - For current working directory Cloud provider Enables the consumption of connections from a cloud provider, such as a specific Azure Machine Learning workspace or Azure AI project. Specify the resource ID in a config.json file placed in the project folder. Click here for more details A dynamic approach for consuming connections from different providers in specific projects. Allows for setting different provider configurations for different flows by updating the config.json in the project folder.
Azure AI connection - For this machine Cloud Enables the consumption of connections from a cloud provider, such as a specific Azure Machine Learning workspace or Azure AI project. Use a connection string to specify a cloud resource as the provider on your local machine. Click here for more details A global provider setting that applies across all working directories on your machine.

Next steps


Cloud Azureai Create Run With Compute Session (`docs/cloud/azureai/create-run-with-compute-session.md`)

Create run with compute session

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

A prompt flow compute session provides computing resources that are required for the application to run, including a Docker image that contains all necessary dependency packages. This reliable and scalable compute session environment enables prompt flow to efficiently execute its tasks and functions for a seamless user experience.

If you're a new user, we recommend that you use the compute session (preview). You can easily customize the environment by adding packages in the requirements.txt file in flow.dag.yaml in the flow folder.

Create a run with compute session

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
pfazure run create --flow path/to/flow --data path/to/data --stream

:::

:::{tab-item} SDK
:sync: SDK

python
from promptflow.azure import PFClient


pf = PFClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",  # this will look like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)
pf.run(
    flow=flow,
    data=data,
)

:::
::::

Specify pip requirements for compute session

If requirements.txt exists in the same folder with flow.dag.yaml.
The dependencies in it will be automatically installed for compute session.

You can also specify which requirements file to use in flow.dag.yaml like this:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
environment:
  python_requirements_txt: path/to/requirement/file
...

Reference Flow YAML Schema for details.

Customize compute session

In compute session case, you can also specify the instance type, if you don't specify the instance type, Azure Machine Learning chooses an instance type (VM size) based on factors like quota, cost, performance and disk size, learn more about serverless compute.

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Run.schema.json
flow: <path_to_flow>
data: <path_to_flow>/data.jsonl

column_mapping:
  url: ${data.url}

# define instance type only work for compute session.
resources:
  instance_type: <instance_type>

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
pfazure run create --file run.yml

:::

:::{tab-item} SDK
:sync: SDK

python
from promptflow.client import load_run

run = load_run(source="run.yml")
pf = PFClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",  # this will look like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)
pf.runs.create_or_update(
    run=run
)

:::
::::

Next steps

  • Try the example here.

Cloud Azureai Deploy To Azure Appservice (`docs/cloud/azureai/deploy-to-azure-appservice.md`)

Deploy to Azure App Service

Azure App Service is an HTTP-based service for hosting web applications, REST APIs, and mobile back ends.
The scripts (deploy.sh for bash and deploy.ps1 for powershell) under this folder are here to help deploy the docker image to Azure App Service.

This example demos how to deploy web-classification deploy a flow using Azure App Service.

Build a flow as docker format app

Use the command below to build a flow as docker format app:

bash
pf flow build --source ../../flows/standard/web-classification --output dist --format docker

Note that all dependent connections must be created before building as docker.

Deploy with Azure App Service

The two scripts will do the following things:

  1. Create a resource group if not exists.
  2. Build and push the image to docker registry.
  3. Create an app service plan with the given sku.
  4. Create an app with specified name, set the deployment container image to the pushed docker image.
  5. Set up the environment variables for the app.

::::{tab-set}
:::{tab-item} Bash
Example command to use bash script:

shell
bash deploy.sh --path dist -i <image_tag> --name my-app-23d8m -r <docker registry> -g <resource_group>

See the full parameters by bash deploy.sh -h.
:::
:::{tab-item} PowerShell
Example command to use powershell script:

powershell
.\deploy.ps1 -Path dist -i <image_tag> -n my-app-23d8m -r <docker registry> -g <resource_group>

See the full parameters by .\deploy.ps1 -h.
:::
::::

Note that the name will produce a unique FQDN as AppName.azurewebsites.net.

View and test the web app

The web app can be found via azure portal

After the app created, you will need to go to https://portal.azure.com/ find the app and set up the environment variables
at (Settings>Configuration) or (Settings>Environment variables), then restart the app.

The app can be tested by sending a POST request to the endpoint or browse the test page.
::::{tab-set}
:::{tab-item} Bash

bash
curl https://<name>.azurewebsites.net/score --data '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -X POST  -H "Content-Type: application/json"

:::
:::{tab-item} PowerShell

powershell
Invoke-WebRequest -URI https://<name>.azurewebsites.net/score -Body '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -Method POST  -ContentType "application/json"

:::
:::{tab-item} Test Page
Browse the app at Overview and see the test page:

:::
::::

Tips:

  • Reach deployment logs at (Deployment>Deployment Central) and app logs at (Monitoring>Log stream).
  • Reach advanced deployment tools at (Development Tools>Advanced Tools).
  • Reach more details about app service at Azure App Service.

Next steps

  • Try the example here.

Cloud Azureai Faq (`docs/cloud/azureai/faq.md`)

Frequency asked questions (FAQ)

How to create feedback for azure portal experience

For azure portal experience related issues, please create feedback on azure portal.

Token expired when run pfazure cmd

If hit error "AADSTS700082: The refresh token has expired due to inactivity." when running pfazure cmd, it's caused by local cached token expired. Please clear the cached token under "%LOCALAPPDATA%/.IdentityService/msal.cache". Then run below command to login again:

sh
az login

Cloud Azureai Generate Test Data Cloud (`docs/cloud/azureai/generate-test-data-cloud.md`)

How to generate test data in cloud based on documents

This guide will help you learn how to generate test data on Azure AI, so that you can integrate the created flow and process a large amount of data.

Prerequisites

  1. Go through local test data generation guide and prepare your test data generation flow.

  2. Go to the example_gen_test_data folder and run command pip install -r requirements_cloud.txt to prepare local environment.

  3. Prepare cloud environment.

    • Navigate to file conda.yml.
    • For specific document file types, you may need to install extra packages:
      • .docx - pip install docx2txt
      • .pdf - pip install pypdf
      • .ipynb - pip install nbconvert

      !Note: We use llama index SimpleDirectoryReader to load documents. For the latest information on required packages, please check here.

  4. Prepare Azure AI resources in cloud.

  5. Create cloud AzureOpenAI or OpenAI connection

  6. Prepare test data generation setting.

Generate test data at cloud

For handling larger test data, you can leverage the PRS component to run flow in cloud.

  • Navigate to example_gen_test_data folder.

  • After configuration, run the following command to generate the test data set:

    bash
    python -m generate-test-data.run --cloud
  • The generated test data will be a data asset which can be found in the output of the last node. You can register this data asset for future use.


Cloud Azureai Manage Flows (`docs/cloud/azureai/manage-flows.md`)

Manage flows

This documentation will walk you through how to manage your flow with CLI and SDK on Azure AI.
The flow examples in this guide come from examples/flows/standard.

In general:

  • For CLI, you can run pfazure flow --help in the terminal to see help messages.
  • For SDK, you can refer to Promptflow Python Library Reference and check promptflow.azure.PFClient.flows for more flow operations.

:::{admonition} Prerequisites

  • Refer to the prerequisites in Quick start.
  • Use the az login command in the command line to log in. This enables promptflow to access your credentials.
    :::

Let's take a look at the following topics:

Create a flow

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

To set the target workspace, you can either specify it in the CLI command or set default value in the Azure CLI.
You can refer to Quick start for more information.

To create a flow to Azure from local flow directory, you can use

bash
# create the flow 
pfazure flow create --flow <path-to-flow-folder> 

# create the flow with metadata
pfazure flow create --flow <path-to-flow-folder> --set display_name=<display-name> description=<description> tags.key1=value1

After the flow is created successfully, you can see the flow summary in the command line.

:::

:::{tab-item} SDK
:sync: SDK

  1. Import the required libraries
python
from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential
# azure version promptflow apis
from promptflow.azure import PFClient
  1. Get credential
python
try:
    credential = DefaultAzureCredential()
    # Check if given credential can get token successfully.
    credential.get_token("https://management.azure.com/.default")
except Exception as ex:
    # Fall back to InteractiveBrowserCredential in case DefaultAzureCredential not work
    credential = InteractiveBrowserCredential()
  1. Get a handle to the workspace
python
# Get a handle to workspace
pf = PFClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",  # this will look like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)
  1. Create the flow
python
# specify flow path
flow = "./web-classification"

# create flow to Azure
flow = pf.flows.create_or_update(
    flow=flow,  # path to the flow folder
    display_name="my-web-classification",  # it will be "web-classification-{timestamp}" if not specified
    type="standard",  # it will be "standard" if not specified
)

:::

::::

On Azure portal, you can see the created flow in the flow list.

And the flow source folder on file share is Users/<alias>/promptflow/<flow-display-name>:

Note that if the flow display name is not specified, it will default to the flow folder name + timestamp. (e.g. web-classification-11-13-2023-14-19-10)

List flows

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

List flows with default json format:

bash
pfazure flow list --max-results 1

:::

:::{tab-item} SDK
:sync: SDK

python
# reuse the pf client created in "create a flow" section
flows = pf.flows.list(max_results=1)

:::

::::


Cloud Azureai Run Promptflow In Azure Ai (`docs/cloud/azureai/run-promptflow-in-azure-ai.md`)

Run prompt flow in Azure AI

Assuming you have learned how to create and run a flow following Quick start. This guide will walk you through the main process of how to submit a promptflow run to Azure AI.

Benefits of use Azure AI comparison to just run locally:

  • Designed for team collaboration: Portal UI is a better fix for sharing & presentation your flow and runs. And workspace can better organize team shared resources like connections.
  • Enterprise Readiness Solutions: prompt flow leverages Azure AI's robust enterprise readiness solutions, providing a secure, scalable, and reliable foundation for the development, experimentation, and deployment of flows.

Prerequisites

  1. An Azure account with an active subscription - Create an account for free
  2. An Azure AI ML workspace - Create workspace resources you need to get started with Azure AI.
  3. A python environment, python=3.9 or higher version like 3.10 is recommended.
  4. Install promptflow with extra dependencies and promptflow-tools.
sh
pip install promptflow[azure] promptflow-tools
  1. Clone the sample repo and check flows in folder examples/flows.
sh
git clone https://github.com/microsoft/promptflow.git

Create necessary connections

Connection helps securely store and manage secret keys or other sensitive credentials required for interacting with LLM and other external tools for example Azure Content Safety.

In this guide, we will use flow web-classification which uses connection open_ai_connection inside, we need to set up the connection if we haven't added it before.

Please go to workspace portal, click Prompt flow -> Connections -> Create, then follow the instruction to create your own connections. Learn more on connections.

Submit a run to workspace

Assuming you are in working directory /examples/flows/standard/

::::{tab-set}

:::{tab-item} CLI
:sync: CLI

Use az login to login so promptflow can get your credential.

sh
az login

Submit a run to workspace.

sh
pfazure run create --subscription <my_sub> -g <my_resource_group> -w <my_workspace> --flow web-classification --data web-classification/data.jsonl --stream

Default subscription/resource-group/workspace

Note --subscription, -g and -w can be omitted if you have installed the Azure CLI and set the default configurations.

sh
az account set --subscription <my-sub>
az configure --defaults group=<my_resource_group> workspace=<my_workspace>

Specify run name and view a run

You can also name the run by specifying --name my_first_cloud_run in the run create command, otherwise the run name will be generated in a certain pattern which has timestamp inside.

With a run name, you can easily stream or view the run details using below commands:

sh
pfazure run stream -n my_first_cloud_run  # same as "--stream" in command "run create"
pfazure run show-details -n my_first_cloud_run
pfazure run visualize -n my_first_cloud_run

More details can be found in CLI reference: pfazure

:::

:::{tab-item} SDK
:sync: SDK

  1. Import the required libraries
python
from azure.identity import DefaultAzureCredential, InteractiveBrowserCredential
# azure version promptflow apis
from promptflow.azure import PFClient
  1. Get credential
python
try:
    credential = DefaultAzureCredential()
    # Check if given credential can get token successfully.
    credential.get_token("https://management.azure.com/.default")
except Exception as ex:
    # Fall back to InteractiveBrowserCredential in case DefaultAzureCredential not work
    credential = InteractiveBrowserCredential()
  1. Get a handle to the workspace
python
# Get a handle to workspace
pf = PFClient(
    credential=credential,
    subscription_id="<SUBSCRIPTION_ID>",  # this will look like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    resource_group_name="<RESOURCE_GROUP>",
    workspace_name="<AML_WORKSPACE_NAME>",
)
  1. Submit the flow run
python
# load flow
flow = "web-classification"
data = "web-classification/data.jsonl"

# create run
base_run = pf.run(
    flow=flow,
    data=data,
)

pf.stream(base_run)
  1. View the run info
python
details = pf.get_details(base_run)
details.head(10)

pf.visualize(base_run)

:::

::::

View the run in workspace

At the end of stream logs, you can find the portal_url of the submitted run, click it to view the run in the workspace.

Run snapshot of the flow with additional includes

Flows that enabled additional include files can also be submitted for execution in the workspace. Please note that the specific additional include files or folders will be uploaded and organized within the Files folder of the run snapshot in the cloud.

Next steps

Learn more about:


Cloud Azureai Runtime Change Log (`docs/cloud/azureai/runtime-change-log.md`)

Change log of default runtime image

Runtime image

In Azure Machine Learning prompt flow, runtime provides the environment to execute flows. The default runtime includes a pre-built Docker image, which contains all necessary dependent packages.

Pull image

The image can be pulled by specifying a runtime version and executing the following command:

text
docker pull mcr.microsoft.com/azureml/promptflow/promptflow-runtime-stable:<runtime_version>

Check image version

You can check the runtime image version from the flow execution log:

Change log

Default runtime image is continuously updated, and here we record the new features and fixed bugs of each image version.

20251211.v2

New features

  • NA

Bugs fixed

  • Upgrade pip==25.3 go==1.24.9 mlflow>=3.6.0 to fix vulnerabilities

20251014.v1

New features

  • NA

Bugs fixed

  • fix GNU C Library and dpkg vulnerabilities in Ubuntu Image

20250831.v1

New features

  • NA

Bugs fixed

  • Update Ubuntu Image 22.04:latest to fix several security issues in Perl and SQLite

20250806.v3

New features

  • NA

Bugs fixed

  • Upgrade aiohttp>=3.12.14 to fix vulnerability

20250728.v1

New features

  • NA

Bugs fixed

  • Update Ubuntu Image 22.04 to fix several security issues in libssh and Git

20250220.v2

New features

  • Update promptflow-tools to 1.6.0

Bugs fixed

  • Pin marshmallow to ensure compatibility with older versions of promptflow for customer use.

20250131.v2

Promptflow version 1.17.1 or higher is required due to a known issue with marshmallow.

New features

  • Update promptflow-tools to 1.5.0
  • Update promptflow to 1.17.2

Bugs fixed

NA

20250109.v2

New features

  • Update promptflow to 1.17.0
  • PromptFlow-vectordb package update : To support langchain 0.3.x

Bugs fixed

  • Update golang crypto, net to fix vulnerabilities
  • Pin aiohttp in runtime image to fix vulnerability

20241214.v1

Do not use this version due to known issues and bugs.

New features

NA

Bugs fixed

  • Update langchain-community>=0.3.0 to fix vulnerability
  • Update mlflow>=2.16.0 to fix vulnerability

20241126.v3

New features

  • Upgrade promptflow version to 1.16.2

Bugs fixed

NA

20241114.v2

New features

NA

Bugs fixed

  • Update langchain-community>=0.2.19 to fix vulnerability

20241031.v1

New features

  • Upgrade promptflow version to 1.16.1

Bugs fixed

NA

20241021.v1

New features

NA

Bugs fixed

  • Upgrade langchain>=0.2.5 and langchain-community>=0.2.5,<0.3.0,!=0.2.14 to fix vulnerability

20240918.v2

New features

NA

Bugs fixed

NA

20240909.v2

New features

NA

Bugs fixed

NA

20240829.v1

New features

NA

Bugs fixed

  • Add uvicorn dependency explicitly

20240814.v1

New features

NA

Bugs fixed

  • Fix non serializable search results

20240731.v1

New features

  • Add Reranker tool with Cohere accessibility to Prompt flow

Bugs fixed

  • Fix run id duplicate check
  • Upgrade langchain version in promptflow-vectordb-sdk

20240709.v1

New features

  • cosmos db vector db support
  • Build and publish promptflow-parallel

Bugs fixed

  • Add aad auth check
  • Fix metadata parser error

20240619.v2

New features

NA

Bugs fixed

  • Add @blob_error_handling_decorator for cancelling_run and get_run_status in async storage
  • Use dataplane api to list embedding deployments
  • Fix KeyError when get run meet UserAuthenticationValidationError.

20240529.v1

New features

  • [BYOI] Implement PostgreSQL
  • [Lookup tool] Implement BYO-Weaviate Index

Bugs fixed

  • The destination of _download_fileshare_directory should be str
  • Passing DefaultAzureCredential into as_langchain_vectorstore
  • Upgrade Werkzeug to 3.0.3.

20240515.v1

New features

  • runtime support batch run prompty
  • Support init_kwargs for multi-container c# batch run
  • Upgrade gunicorn and mlflow

Bugs fixed

  • Fix and avoid FlowExecutor in PythonApiExecutorProxy

20240511.v1

New features

  • Add support for more huggingface models

Bugs fixed

  • _download_azure_file_share should return str
  • When ingress call gunicorn met timeout, we should not return 200.
  • Pin azureml-rag version to 0.2.30.2
  • Upgrade golang.org/x/net from 0.17.0 to 0.23.0 to fix vulnerability

20240429.v8

New features

  • Remove preview tag from Index Lookup
  • Support init_kwargs in c# batch run in cloud

Bugs fixed

  • Pass init_kwargs to executor in multi container case
  • Fix error of span.attributes.flow_log_path in multi-container.
  • Add duplicated key in SystemLogContext to avoid breaking when LogContext does not have it
  • Add clarification to migration notebook and small fixes
  • [Lookup tool] Update list pinecone index endpoint
  • Handle case where flow_logs_folder is None

20240424.v1

New features

  • Support download working_dir from fileshare.
  • Enable line log for batch run
  • Add prompt_tokens/completion_tokens to run properties
  • Support C# batch run in multi-container runtime
  • Implement ESIndex in common index lookup
  • Handle metadata processing better in Index Lookup
  • implement mongodb support

Bugs fixed

  • Remove Promptflow-evals publish.
  • [Lookup tool] Add workspace name in get()
  • changes to utils.py were accidentally left out of previous PR.

20240411.v4

New features

  • Add 'detail' parameter on 'Azure OpenAI GPT-4 Turbo with Vision" tool and "OpenAI GPT-4V" tool.

Bugs fixed

  • Resolve an intermittent ImportError that arose while loading the package tool.
  • Upgrade langchain>=0.1.1 and langchain-core>=0.1.30 to fix vulnerability.

20240403.v2

New features

NA

Bugs fixed

NA

20240326.v2

New features

  • Support environment variables for C# batch run.

Bugs fixed

NA

20240319.v1

New features

NA

Bugs fixed

NA

20240313.v1

New features

NA

Bugs fixed

  • Fix an issue where calling a flow with a flow function would result in failure.
  • Improve error handling by categorizing errors as user errors when a run is archived prior to being processed by the runtime.

20240306.v5

New features

  • Support "seed" parameter for built-in LLM tools and GPT-4V tools.

Bugs fixed

  • Handle ClientAuthenticationError properly.
  • Fix appending blob exceeded size limit error by truncating debug info.

20240228.v3

New features

  • Support async flow test for long running jobs.

Bugs fixed

  • Fix bug when collecting package tools.

20240222.v3

New features

  • Added support for executing C# batch runs in eager mode.
  • Introduced the ability to specify the number of workers for batch runs.
  • Implemented functionality to define a timeout for batch runs.

Bugs fixed

NA

20240205.v2

New features

NA

Bugs fixed

  • Fix the bug that deployed promptflow endpoint fails to get user assigned identity token.

20240124.v3

New features

  • Support downloading data from Azure Machine Learning registry for batch run.
  • Show node status when one line of a batch run times out.

Bugs fixed

  • Fix the bug that exception raised during preparing data is not set in run history.
  • Fix the bug that unexpected exception is raised when executor process crushes.

20240116.v1

New features

NA

Bugs fixed

  • Add validation for wrong connection type for LLM tool.

20240111.v2

New features

  • Support error log scrubbing for heron jobs.

Bugs fixed

  • Fixed the compatibility issue between runtime and promptflow package < 1.3.0

Cloud Azureai Use Flow In Azure Ml Pipeline (`docs/cloud/azureai/use-flow-in-azure-ml-pipeline.md`)

Use flow in Azure ML pipeline job

In practical scenarios, flows fulfill various functions. For example, consider an offline flow specifically designed to assess the relevance score for communication sessions between humans and agents. This flow is triggered nightly and processes a substantial amount of session data. In such a context, Parallel component and AzureML pipeline emerge as the optimal choices for handling large-scale, highly resilient, and efficient offline batch requirements.

Once you’ve developed and thoroughly tested your flow, this guide will walk you through utilizing your flow as a parallel component within an AzureML pipeline job.

:::{admonition} Pre-requirements
To enable this feature, customer need to:

  1. install related CLI or package:
    1. For CLI, please install Azure CLI first and then install the extension ml>=2.22.0 via az extension add -n ml;
    2. For SDK, please install package azure-ai-ml>=1.12.0 via pip install azure-ai-ml>=1.12.0 or pip install promptflow[azure];
  2. ensure that there is a $schema in the target source:
    1. flow.dag.yaml: $schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
    2. run.yaml: $schema: https://azuremlschemas.azureedge.net/promptflow/latest/Run.schema.json
  3. ensure that metadata has been generated and is up-to-date:
    1. <my-flow-directory>/.promptflow/flow.tools.json should exist;
    2. customer may update the file via pf flow validate --source <my-flow-directory>.

:::

To explore an executable end-to-end example of running sample flow within Azure ML workspace, you can refer to this tutorial notebook: run flow with pipeline

For more information about AzureML and component:

Register a flow as a component

Suppose there has been a flow and its flow.dag.yaml is as below:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
environment:
  python_requirements_txt: requirements.txt
inputs:
  text:
    type: string
    default: Hello World!
outputs:
  output:
    type: string
    reference: ${llm.output}
nodes:
- name: hello_prompt
  type: prompt
  source:
    type: code
    path: hello.jinja2
  inputs:
    text: ${inputs.text}
- name: llm
  type: python
  source:
    type: code
    path: hello.py
  inputs:
    prompt: ${hello_prompt.output}
    deployment_name: text-davinci-003
    max_tokens: "120"

Customer can register a flow as a component with either CLI or SDK:

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
# Register flow as a component
az ml component create --file \<my-flow-directory\>/flow.dag.yaml

# Register flow as a component and specify its name and version
# Default component name will be the name of flow folder, which can be invalid as a component name; default version will be "1"
az ml component create --file \<my-flow-directory\>/flow.dag.yaml --version 3 --set name=basic_updated

:::

:::{tab-item} SDK
:sync: SDK

python
from azure.ai.ml import MLClient, load_component

ml_client = MLClient()

# Register flow as a component
flow_component = load_component("<my-flow-directory>/flow.dag.yaml")
ml_client.components.create_or_update(flow_component)

# Register flow as a component and specify its name and version
# Default component name will be the name of flow folder, which can be invalid as a component name; default version will be "1"
flow_component.name = "basic_updated"
ml_client.components.create_or_update(flow_component, version="3")

:::

::::

The generated component will be a parallel component, whose definition will be as below:

yaml
name: basic
version: 1
display_name: basic
is_deterministic: True
type: parallel
inputs:
  data:
    type: uri_folder
    optional: False
  run_outputs:
    type: uri_folder
    optional: True
  text:
    type: string
    optional: False
    default: Hello World!
outputs:
  flow_outputs:
    type: uri_folder
  debug_info:
    type: uri_folder
...

Besides the fixed input/output ports, all connections and flow inputs will be exposed as input parameters of the component. Default value can be provided in flow/run definition; they can also be set/overwrite on job submission. Full description of ports can be seen in section Component ports and run settings.

Use a flow in a pipeline job

After registered a flow as a component, they can be referred in a pipeline job like regular registered components. Customer may also directly use a flow in a pipeline job, then anonymous components will be created on job submission.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

yaml
...
inputs:
  basic_input:
    type: uri_file
    path: <path-to-data>
compute: azureml:cpu-cluster
jobs:
  flow_from_registered:
    type: parallel
    component: azureml:my_flow_component:1
    inputs:
      data: ${{parent.inputs.basic_input}}
      text: "${data.text}"
  flow_from_dag:
    type: parallel
    component: <path-to-flow-dag-yaml>
    inputs:
      data: ${{parent.inputs.basic_input}}
      text: "${data.text}"
  flow_from_run:
    type: parallel
    component: <path-to-run-yaml>
    inputs:
      data: ${{parent.inputs.basic_input}}
      text: "${data.text}"
...

Pipeline job can be submitted via az ml job create --file pipeline.yml.

Full example can be found here.

:::

:::{tab-item} SDK
:sync: SDK

python
from azure.identity import DefaultAzureCredential
from azure.ai.ml import MLClient, load_component, Input
from azure.ai.ml.dsl import pipeline

credential = DefaultAzureCredential()
ml_client = MLClient.from_config(credential=credential)
data_input = Input(path="<path-to-data>", type='uri_file')

flow_component_from_registered = ml_client.components.get("my_flow_component", "1")
flow_component_from_dag = load_component("<path-to-flow-dag-yaml>")
flow_component_from_run = load_component("<path-to-run-yaml>")

@pipeline
def pipeline_func_with_flow(basic_input):
    flow_from_registered = flow_component_from_registered(
        data=data,
        text="${data.text}",
    )
    flow_from_dag = flow_component_from_dag(
        data=data,
        text="${data.text}",
    )
    flow_from_run = flow_component_from_run(
        data=data,
        text="${data.text}",
    )

pipeline_with_flow = pipeline_func_with_flow(basic_input=data_input)
pipeline_with_flow.compute = "cpu-cluster"

pipeline_job = ml_client.jobs.create_or_update(pipeline_with_flow)
ml_client.jobs.stream(pipeline_job.name)

Full example can be found here.

:::

::::

Like regular parallel components, customer may specify run settings for them in a pipeline job. Some regularly used run settings have been listed in section Component ports and run settings; customer may also refer to the official document of parallel component for more details:

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

yaml
...
jobs:
  flow_node:
    type: parallel
    component: <path-to-complicated-run-yaml>
    compute: azureml:cpu-cluster
    instance_count: 2
    max_concurrency_per_instance: 2
    mini_batch_error_threshold: 5
    retry_settings:
      max_retries: 3
      timeout: 30
    inputs:
      data: ${{parent.inputs.data}}
      url: "${data.url}"
      connections.summarize_text_content.connection: azure_open_ai_connection
      connections.summarize_text_content.deployment_name: text-davinci-003
      environment_variables.AZURE_OPENAI_API_KEY: ${my_connection.api_key}
      environment_variables.AZURE_OPENAI_API_BASE: ${my_connection.api_base}
...

:::

:::{tab-item} SDK
:sync: SDK

python
from azure.identity import DefaultAzureCredential
from azure.ai.ml import MLClient, load_component, Input
from azure.ai.ml.dsl import pipeline
from azure.ai.ml.entities import RetrySettings

credential = DefaultAzureCredential()
ml_client = MLClient.from_config(credential=credential)
data_input = Input(path="<path-to-data>", type='uri_file')

# Load flow as a component
flow_component = load_component("<path-to-complicated-run-yaml>")

@pipeline
def pipeline_func_with_flow(data):
    flow_node = flow_component(
        data=data,
        url="${data.url}",
        connections={
            "summarize_text_content": {
                "connection": "azure_open_ai_connection",
                "deployment_name": "text-davinci-003",
            },
        },
        environment_variables={
            "AZURE_OPENAI_API_KEY": "${my_connection.api_key}",
            "AZURE_OPENAI_API_BASE": "${my_connection.api_base}",
        }
    )
    flow_node.compute = "cpu-cluster"
    flow_node.instance_count = 2
    flow_node.max_concurrency_per_instance = 2
    flow_node.mini_batch_error_threshold = 5
    flow_node.retry_settings = RetrySettings(timeout=30, max_retries=5)

pipeline_with_flow = pipeline_func_with_flow(data=data_input)

pipeline_job = ml_client.jobs.create_or_update(pipeline_with_flow)
ml_client.jobs.stream(pipeline_job.name)

:::

::::

Environment of the component

By default, the environment of the created component will be based on the latest promptflow runtime image. If customer has specified python requirement file in flow.dag.yaml, they will be applied to the environment automatically:

yaml
...
environment:
  python_requirements_txt: requirements.txt

If customer want to use an existing Azure ML environment or define the environment in Azure ML style, they can define it in run.yaml like below:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Run.schema.json
flow: <my-flow-directory>
azureml:
  environment: azureml:my-environment:1

For more details about the supported format of Azure ML environment, please refer to this doc.

Difference across flow in prompt flow and pipeline job

In prompt flow, flow runs on compute session, which is designed for prompt flow; while in pipeline job, flow runs on different types of compute, and usually compute cluster.

Given above, if your flow has logic relying on identity or environment variable, please be aware of this difference as you might run into some unexpected error(s) when the flow runs in pipeline job, and you might need some extra configurations to make it work.

Component ports and run settings

Input ports

key source type description
data fixed uri_folder or uri_file required; to pass in input data. Supported format includes mltable and list of jsonl files.
run_outputs fixed uri_folder optional; to pass in output of a standard flow for an evaluation flow. Should be linked to a flow_outputs of a previous flow node in the pipeline.

Output ports

key source type description
flow_outputs fixed uri_folder an uri_folder with 1 or more jsonl files containing outputs of the flow runs
debug_info fixed uri_folder an uri_folder containing debug information of the flow run, e.g., run logs

Parameters

key source type description
<flow-input-name> from flow inputs string default value will be inherited from flow inputs; used to override column mapping for flow inputs.
connections.<node-name>.connection from nodes of built-in LLM tools string default value will be current value defined in flow.dag.yaml or run.yaml; to override used connections of corresponding nodes. Connection should exist in current workspace.
connections.<node-name>.deployment_name from nodes of built-in LLM tools string default value will be current value defined in flow.dag.yaml or run.yaml; to override target deployment names of corresponding nodes. Deployment should be available with provided connection.
connections.<node-name>.<node-input-key> from nodes with Connection inputs string default value will be current value defined in flow.dag.yaml or run.yaml; to override used connections of corresponding nodes. Connection should exist in current workspace.
environment_variables.<environment-variable-name> from environment variables defined in run.yaml string default value will be the current value defined in run.yaml; to override environment variables during flow run, e.g. AZURE_OPENAI_API_KEY. Note that you can refer to workspace connections with expressions like {my_connection.api_key}.

Run settings

key type Description
instance_count integer The number of nodes to use for the job. Default value is 1.
max_concurrency_per_instance integer The number of processors on each node.
mini_batch_error_threshold integer Define the number of failed mini batches that could be ignored in this parallel job. If the count of failed mini-batch is higher than this threshold, the parallel job will be marked as failed.Mini-batch is marked as failed if:- the count of return from run() is less than mini-batch input count.- catch exceptions in custom run() code."-1" is the default number, which means to ignore all failed mini-batch during parallel job.
retry_settings.max_retries integer Define the number of retries when mini-batch is failed or timeout. If all retries are failed, the mini-batch will be marked as failed to be counted by mini_batch_error_threshold calculation.
retry_settings.timeout integer Define the timeout in seconds for executing custom run() function. If the execution time is higher than this threshold, the mini-batch will be aborted, and marked as a failed mini-batch to trigger retry.
logging_level INFO, WARNING, or DEBUG Define which level of logs will be dumped to user log files.

Check the official document of parallel component for more run settings.


How To Guides Deploy A Flow Deploy Using Dev Server (`docs/how-to-guides/deploy-a-flow/deploy-using-dev-server.md`)

Deploy a flow using development server

Once you have created and thoroughly tested a flow, you can use it as an HTTP endpoint.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
We are going to use the web-classification as
an example to show how to deploy a flow.

Please ensure you have create the connection required by flow, if not, you could
refer to Setup connection for web-classification.

Note: We will use relevant environment variable ({connection_name}_{key_name}) to override connection configurations in
serving mode, white space in connection name will be removed directly from environment variable name. For instance,
if there is a custom connection named 'custom_connection' with a configuration key called 'chat_deployment_name,' the
function will attempt to retrieve 'chat_deployment_name' from the environment variable
'CUSTOM_CONNECTION_CHAT_DEPLOYMENT_NAME' by default. If the environment variable is not set, it will use the original
value as a fallback.

The following CLI commands allows you serve a flow folder as an endpoint. By running this command, a flask app will start in the environment where command is executed, please ensure all prerequisites required by flow have been installed.

bash
# Serve the flow at localhost:8080
pf flow serve --source <path-to-your-flow-folder> --port 8080 --host localhost

The expected result is as follows if the flow served successfully, and the process will keep alive until it be killed manually.

:::
:::{tab-item} VS Code Extension
:sync: VSC
In visual editor, choose:

then choose format:

then in yaml editor:

:::
::::

Test endpoint

::::{tab-set}
:::{tab-item} Bash
You could open another terminal to test the endpoint with the following command:

bash
curl http://localhost:8080/score --data '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -X POST  -H "Content-Type: application/json"

:::
:::{tab-item} PowerShell
You could open another terminal to test the endpoint with the following command:

powershell
Invoke-WebRequest -URI http://localhost:8080/score -Body '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -Method POST  -ContentType "application/json"

:::
:::{tab-item} Test Page
The development server has a built-in web page you can use to test the flow. Open 'http://localhost:8080' in your browser.

:::
::::

Next steps


How To Guides Deploy A Flow Deploy Using Docker (`docs/how-to-guides/deploy-a-flow/deploy-using-docker.md`)

Deploy a flow using Docker

There are two steps to deploy a flow using docker:

  1. Build the flow as docker format.
  2. Build and run the docker image.

Build a flow as docker format

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Use the command below to build a flow as docker format:

bash
pf flow build --source <path-to-your-flow-folder> --output <your-output-dir> --format docker

:::
:::{tab-item} VS Code Extension
:sync: VSC

In visual editor, choose:

Click the button below to build a flow as docker format:

:::
::::

Note that all dependent connections must be created before exporting as docker.

Docker format folder structure

Exported Dockerfile & its dependencies are located in the same folder. The structure is as below:

  • flow: the folder contains all the flow files
    • ...
  • connections: the folder contains yaml files to create all related connections
    • ...
  • Dockerfile: the dockerfile to build the image
  • start.sh: the script used in CMD of Dockerfile to start the service
  • runit: the folder contains all the runit scripts
    • ...
  • settings.json: a json file to store the settings of the docker image
  • README.md: Simple introduction of the files

Deploy with Docker

We are going to use the web-classification as
an example to show how to deploy with docker.

Please ensure you have create the connection required by flow, if not, you could
refer to Setup connection for web-classification.

Build a flow as docker format app

Use the command below to build a flow as docker format app:

bash
pf flow build --source ../../flows/standard/web-classification --output dist --format docker

Note that all dependent connections must be created before exporting as docker.

Build Docker image

Like other Dockerfile, you need to build the image first. You can tag the image with any name you want. In this example, we use web-classification-serve.

Run the command below to build image:

bash
docker build dist -t web-classification-serve

Run Docker image

Run the docker image will start a service to serve the flow inside the container.

Connections

If the service involves connections, all related connections will be exported as yaml files and recreated in containers.
Secrets in connections won't be exported directly. Instead, we will export them as a reference to environment variables:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/OpenAIConnection.schema.json
type: open_ai
name: open_ai_connection
module: promptflow.connections
api_key: ${env:OPEN_AI_CONNECTION_API_KEY} # env reference

You'll need to set up the environment variables in the container to make the connections work.

Run with `docker run`

Run with `flask` serving engine

You can run the docker image directly set via below commands, this will by default use flask serving engine:

bash
# The started service will listen on port 8080.You can map the port to any port on the host machine as you want.
docker run -p 8080:8080 -e OPEN_AI_CONNECTION_API_KEY=<secret-value> -e PROMPTFLOW_WORKER_NUM=<expect-worker-num> -e PROMPTFLOW_WORKER_THREADS=<expect-thread-num-per-worker> web-classification-serve

Note that:

  • PROMPTFLOW_WORKER_NUM: optional setting, it controls how many workers started in your container, default value is 8.
  • PROMPTFLOW_WORKER_THREADS: optional setting, it controls how many threads started in one worker, default value is 1. this setting only works for flask engine

Run with `fastapi` serving engine

Starting from pf 1.10.0, we support new fastapi based serving engine, you can choose to use fastapi serving engine via below commands:

bash
# The started service will listen on port 8080.You can map the port to any port on the host machine as you want.
docker run -p 8080:8080 -e OPEN_AI_CONNECTION_API_KEY=<secret-value> -e PROMPTFLOW_SERVING_ENGINE=fastapi -e PROMPTFLOW_WORKER_NUM=<expect-worker-num> web-classification-serve

Note that:

  • PROMPTFLOW_WORKER_NUM: optional setting, it controls how many workers started in your container, default value is 8.
  • PROMPTFLOW_SERVING_ENGINE: optional setting, it controls which serving engine to use in your container, default value is flask, currently only support flask and fastapi.

Test the endpoint

After start the service, you can use curl to test it:

bash
curl http://localhost:8080/score --data '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -X POST  -H "Content-Type: application/json"

Next steps


How To Guides Deploy A Flow Deploy Using Kubernetes (`docs/how-to-guides/deploy-a-flow/deploy-using-kubernetes.md`)

Deploy a flow using Kubernetes

There are four steps to deploy a flow using Kubernetes:

  1. Build the flow as docker format.
  2. Build the docker image.
  3. Create Kubernetes deployment yaml.
  4. Apply the deployment.

Build a flow as docker format

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Note that all dependent connections must be created before building as docker.

bash
# create connection if not created before
pf connection create --file ../../../examples/connections/azure_openai.yml --set api_key=<your_api_key> api_base=<your_api_base> --name open_ai_connection

Use the command below to build a flow as docker format:

bash
pf flow build --source <path-to-your-flow-folder> --output <your-output-dir> --format docker

:::
:::{tab-item} VS Code Extension
:sync: VSC

Click the button below to build a flow as docker format:

:::
::::

Note that all dependent connections must be created before exporting as docker.

Docker format folder structure

Exported Dockerfile & its dependencies are located in the same folder. The structure is as below:

  • flow: the folder contains all the flow files
    • ...
  • connections: the folder contains yaml files to create all related connections
    • ...
  • Dockerfile: the dockerfile to build the image
  • start.sh: the script used in CMD of Dockerfile to start the service
  • runit: the folder contains all the runit scripts
    • ...
  • settings.json: a json file to store the settings of the docker image
  • README.md: Simple introduction of the files

Deploy with Kubernetes

We are going to use the web-classification as
an example to show how to deploy with Kubernetes.

Please ensure you have create the connection required by flow, if not, you could
refer to Setup connection for web-classification.

Additionally, please ensure that you have installed all the required dependencies. You can refer to the "Prerequisites" section in the README of the web-classification for a comprehensive list of prerequisites and installation instructions.

Build Docker image

Like other Dockerfile, you need to build the image first. You can tag the image with any name you want. In this example, we use web-classification-serve.

Then run the command below:

bash
cd <your-output-dir>
docker build . -t web-classification-serve

Create Kubernetes deployment yaml.

The Kubernetes deployment yaml file acts as a guide for managing your docker container in a Kubernetes pod. It clearly specifies important information like the container image, port configurations, environment variables, and various settings. Below, you'll find a simple deployment template that you can easily customize to meet your needs.

Note: You need encode the secret using base64 firstly and input the as 'open-ai-connection-api-key' in the deployment configuration. For example, you can run below commands in linux:

bash
encoded_secret=$(echo -n <your_api_key> | base64)
yaml
---
kind: Namespace
apiVersion: v1
metadata:
  name: <your-namespace>
---
apiVersion: v1
kind: Secret
metadata:
  name: open-ai-connection-api-key
  namespace: <your-namespace>
type: Opaque
data:
  open-ai-connection-api-key: <encoded_secret>
---
apiVersion: v1
kind: Service
metadata:
  name: web-classification-service
  namespace: <your-namespace>
spec:
  type: NodePort
  ports:
  - name: http
    port: 8080
    targetPort: 8080
    nodePort: 30123
  selector:
    app: web-classification-serve-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-classification-serve-app
  namespace: <your-namespace>
spec:
  selector:
    matchLabels:
      app: web-classification-serve-app
  template:
    metadata:
      labels:
        app: web-classification-serve-app
    spec:
      containers:
      - name: web-classification-serve-container
        image: <your-docker-image>
        imagePullPolicy: Never
        ports:
        - containerPort: 8080
        env:
        - name: OPEN_AI_CONNECTION_API_KEY
          valueFrom:
            secretKeyRef:
              name: open-ai-connection-api-key
              key: open-ai-connection-api-key

Apply the deployment.

Before you can deploy your application, ensure that you have set up a Kubernetes cluster and installed kubectl if it's not already installed. In this documentation, we will use Minikube as an example. To start the cluster, execute the following command:

bash
minikube start

Once your Kubernetes cluster is up and running, you can proceed to deploy your application by using the following command:

bash
kubectl apply -f deployment.yaml

This command will create the necessary pods to run your application within the cluster.

Note: You need replace below with your specific pod_name. You can retrieve it by running kubectl get pods -n web-classification.

Retrieve flow service logs of the container

The kubectl logs command is used to retrieve the logs of a container running within a pod, which can be useful for debugging, monitoring, and troubleshooting applications deployed in a Kubernetes cluster.

bash
kubectl -n <your-namespace> logs <pod-name>

Connections

If the service involves connections, all related connections will be exported as yaml files and recreated in containers.
Secrets in connections won't be exported directly. Instead, we will export them as a reference to environment variables:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/OpenAIConnection.schema.json
type: open_ai
name: open_ai_connection
module: promptflow.connections
api_key: ${env:OPEN_AI_CONNECTION_API_KEY} # env reference

You'll need to set up the environment variables in the container to make the connections work.

Test the endpoint

  • Option1:

    Once you've started the service, you can establish a connection between a local port and a port on the pod. This allows you to conveniently test the endpoint from your local terminal.
    To achieve this, execute the following command:

    bash
    kubectl port-forward <pod_name> <local_port>:<container_port> -n <your-namespace>

    With the port forwarding in place, you can use the curl command to initiate the endpoint test:

    bash
    curl http://localhost:<local_port>/score --data '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -X POST  -H "Content-Type: application/json"
  • Option2:

    minikube service web-classification-service --url -n <your-namespace> runs as a process, creating a tunnel to the cluster. The command exposes the service directly to any program running on the host operating system.

    The command above will retrieve the URL of a service running within a Minikube Kubernetes cluster (e.g. http://:), which you can click to interact with the flow service in your web browser. Alternatively, you can use the following command to test the endpoint:

    Note: Minikube will use its own external port instead of nodePort to listen to the service. So please substitute with the port obtained above.

    bash
    curl http://localhost:<assigned_port>/score --data '{"url":"https://play.google.com/store/apps/details?id=com.twitter.android"}' -X POST  -H "Content-Type: application/json"

Next steps

  • Try the example here.

How To Guides Deploy A Flow Distribute Flow As Executable App (`docs/how-to-guides/deploy-a-flow/distribute-flow-as-executable-app.md`)

Distribute flow as executable app

We are going to use the web-classification as
an example to show how to distribute flow as executable app with Pyinstaller.

Please ensure that you have installed all the required dependencies. You can refer to the "Prerequisites" section in the README of the web-classification for a comprehensive list of prerequisites and installation instructions. And we recommend you to add a requirements.txt to indicate all the required dependencies for each flow.

Pyinstaller is a popular tool used for converting Python applications into standalone executables. It allows you to package your Python scripts into a single executable file, which can be run on a target machine without requiring the Python interpreter to be installed.
Streamlit is an open-source Python library used for creating web applications quickly and easily. It's designed for data scientists and engineers who want to turn data scripts into shareable web apps with minimal effort.
We use Pyinstaller to package the flow and Streamlit to create custom web apps. Prior to distributing the workflow, kindly ensure that you have installed them.

Build a flow as executable format

Note that all dependent connections must be created before building as executable.

bash
# create connection if not created before
pf connection create --file ../../../examples/connections/azure_openai.yml --set api_key=<your_api_key> api_base=<your_api_base> --name open_ai_connection

Use the command below to build a flow as executable format:

bash
pf flow build --source <path-to-your-flow-folder> --output <your-output-dir> --format executable

Executable format folder structure

Exported files & its dependencies are located in the same folder. The structure is as below:

  • flow: the folder contains all the flow files.
  • connections: the folder contains yaml files to create all related connections.
  • app.py: the entry file is included as the entry point for the bundled application.
  • app.spec: the spec file tells PyInstaller how to process your script.
  • main.py: it will start streamlit service and be called by the entry file.
  • settings.json: a json file to store the settings of the executable application.
  • build: a folder contains various log and working files.
  • dist: a folder contains the executable application.
  • README.md: Simple introduction of the files.

A template script of the entry file

PyInstaller reads a spec file or Python script written by you. It analyzes your code to discover every other module and library your script needs in order to execute. Then it collects copies of all those files, including the active Python interpreter, and puts them with your script in a single folder, or optionally in a single executable file.

We provide a Python entry script named app.py as the entry point for the bundled app, which enables you to serve a flow folder as an endpoint.

A template script of the spec file

The spec file tells PyInstaller how to process your script. It encodes the script names and most of the options you give to the pyinstaller command. The spec file is actually executable Python code. PyInstaller builds the app by executing the contents of the spec file.

To streamline this process, we offer a app.spec.jinja2 spec template file that bundles the application into a single file. For additional information on spec files, you can refer to the Using Spec Files. Please replace streamlit_runtime_interpreter_path with the path of streamlit runtime interpreter in your environment.

The bundled application using Pyinstaller

Once you've build a flow as executable format following Build a flow as executable format.
It will create two folders named build and dist within your specified output directory, denoted as . The build folder houses various log and working files, while the dist folder contains the app executable application.

Connections

If the service involves connections, all related connections will be exported as yaml files and recreated in the executable package.
Secrets in connections won't be exported directly. Instead, we will export them as a reference to environment variables:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/OpenAIConnection.schema.json
type: open_ai
name: open_ai_connection
module: promptflow.connections
api_key: ${env:OPEN_AI_CONNECTION_API_KEY} # env reference

Test the endpoint

Finally, You can distribute the bundled application app to other people. They can execute your program by double clicking the executable file, e.g. app.exe in Windows system or running the binary file, e.g. app in Linux system.

The development server has a built-in web page they can use to test the flow by opening 'http://localhost:8501' in the browser. The expected result is as follows: if the flow served successfully, the process will keep alive until it is killed manually.

To your users, the app is self-contained. They do not need to install any particular version of Python or any modules. They do not need to have Python installed at all.

Note: The executable generated is not cross-platform. One platform (e.g. Windows) packaged executable can't run on others (Mac, Linux).

Known issues

  1. Note that Python 3.10.0 contains a bug making it unsupportable by PyInstaller. PyInstaller will also not work with beta releases of Python 3.13.

Next steps

  • Try the example here

How To Guides Develop A Dag Flow Add Conditional Control To A Flow (`docs/how-to-guides/develop-a-dag-flow/add-conditional-control-to-a-flow.md`)

Add conditional control to a flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

In prompt flow, we support control logic by activate config, like if-else, switch. Activate config enables conditional execution of nodes within your flow, ensuring that specific actions are taken only when the specified conditions are met.

This guide will help you learn how to use activate config to add conditional control to your flow.

Prerequisites

Please ensure that your promptflow version is greater than 0.1.0b5.

Usage

Each node in your flow can have an associated activate config, specifying when it should execute and when it should bypass. If a node has activate config, it will only be executed when the activate condition is met. The configuration consists of two essential components:

  • activate.when: The condition that triggers the execution of the node. It can be based on the outputs of a previous node, or the inputs of the flow.
  • activate.is: The condition's value, which can be a constant value of string, boolean, integer, double.

You can manually change the flow.dag.yaml in the flow folder or use the visual editor in VS Code Extension to add activate config to nodes in the flow.

::::{tab-set}
:::{tab-item} YAML
:sync: YAML

You can add activate config in the node section of flow yaml.

yaml
activate:
  when: ${node.output}
  is: true

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

  • Click Visual editor in the flow.dag.yaml to enter the flow interface.

  • Click on the Activation config section in the node you want to add and fill in the values for "when" and "is".

:::

::::

Further details and important notes

  1. If the node using the python tool has an input that references a node that may be bypassed, please provide a default value for this input whenever possible. If there is no default value for input, the output of the bypassed node will be set to None.

  2. It is not recommended to directly connect nodes that might be bypassed to the flow's outputs. If it is connected, the output will be None and a warning will be raised.

  3. In a conditional flow, if a node has an activate config, we will always use this config to determine whether the node should be bypassed. If a node is bypassed, its status will be marked as "Bypassed", as shown in the figure below Show. There are three situations in which a node is bypassed.

    (1) If a node has activate config and the value of activate.when is not equals to activate.is, it will be bypassed. If you want to fore a node to always be executed, you can set the activate config to when dummy is dummy which always meets the activate condition.

    (2) If a node has activate config and the node pointed to by activate.when is bypassed, it will be bypassed.

    (3) If a node does not have activate config but depends on other nodes that have been bypassed, it will be bypassed.

Example flow

Let's illustrate how to use activate config with practical examples.

  • If-Else scenario: Learn how to develop a conditional flow for if-else scenarios. View Example
  • Switch scenario: Explore conditional flow for switch scenarios. View Example

Next steps


How To Guides Develop A Dag Flow Develop Chat Flow (`docs/how-to-guides/develop-a-dag-flow/develop-chat-flow.md`)

Develop chat flow

From this document, you can learn how to develop a chat flow by writing a flow yaml from scratch. You can
find additional information about flow yaml schema in Flow YAML Schema.

Flow input data

The most important elements that differentiate a chat flow from a standard flow are chat input and chat history. A chat flow can have multiple inputs, but chat history and chat input are required inputs in chat flow.

  • Chat Input: Chat input refers to the messages or queries submitted by users to the chatbot. Effectively handling chat input is crucial for a successful conversation, as it involves understanding user intentions, extracting relevant information, and triggering appropriate responses.

  • Chat History: Chat history is the record of all interactions between the user and the chatbot, including both user inputs and AI-generated outputs. Maintaining chat history is essential for keeping track of the conversation context and ensuring the AI can generate contextually relevant responses. Chat history is a special type of chat flow input, that stores chat messages in a structured format.

    An example of chat history:

    python
    [
      {"inputs": {"question": "What types of container software there are?"}, "outputs": {"answer": "There are several types of container software available, including: Docker, Kubernetes"}},
      {"inputs": {"question": "What's the different between them?"}, "outputs": {"answer": "The main difference between the various container software systems is their functionality and purpose. Here are some key differences between them..."}},
    ]

You can set is_chat_input/is_chat_history to true to add chat_input/chat_history to the chat flow.

yaml
inputs:
  chat_history:
    type: list
    is_chat_history: true
    default: []
  question:
    type: string
    is_chat_input: true
    default: What is ChatGPT?

For more information see develop the flow using different tools.

Develop the flow using different tools

In one flow, you can consume different kinds of tools. We now support built-in tool like
LLM, Python and
Prompt and
third-party tool like Serp API,
Vector Search, etc.

For more information see develop the flow using different tools.

Before linking nodes together, you need to define and expose an interface.

For more information see chain your flow.

Set flow output

Chat output is required output in the chat flow. It refers to the AI-generated messages that are sent to the user in response to their inputs. Generating contextually appropriate and engaging chat outputs is vital for a positive user experience.

You can set is_chat_output to true to add chat_output to the chat flow.

yaml
outputs:
  answer:
    type: string
    reference: ${chat.output}
    is_chat_output: true

How To Guides Develop A Dag Flow Develop Evaluation Flow (`docs/how-to-guides/develop-a-dag-flow/develop-evaluation-flow.md`)

Develop evaluation flow

The evaluation flow is a flow to test/evaluate the quality of your LLM application (standard/chat flow). It usually runs on the outputs of standard/chat flow, and compute key metrics that can be used to determine whether the standard/chat flow performs well. See Flows for more information.

Before proceeding with this document, it is important to have a good understanding of the standard flow. Please make sure you have read Develop standard flow, since they share many common features and these features won't be repeated in this doc, such as:

  • Inputs/Outputs definition
  • Nodes
  • Chain nodes in a flow

While the evaluation flow shares similarities with the standard flow, there are some important differences that set it apart. The main distinctions are as follows:

  • Inputs from an existing run: The evaluation flow contains inputs that are derived from the outputs of the standard/chat flow. These inputs are used for evaluation purposes.
  • Aggregation node: The evaluation flow contains one or more aggregation nodes, where the actual evaluation takes place. These nodes are responsible for computing metrics and determining the performance of the standard/chat flow.

Evaluation flow example

In this guide, we use eval-classification-accuracy flow as an example of the evaluation flow. This is a flow illustrating how to evaluate the performance of a classification flow. It involves comparing each prediction to the groundtruth and assigns a Correct or Incorrect grade, and aggregating the results to produce metrics such as accuracy, which reflects how good the system is at classifying the data.

Flow inputs

The flow eval-classification-accuracy contains two inputs:

yaml
inputs:
  groundtruth:
    type: string
    description: Groundtruth of the original question, it's the correct label that you hope your standard flow could predict.
    default: APP
  prediction:
    type: string
    description: The actual predicted outputs that your flow produces.
    default: APP

As evident from the inputs description, the evaluation flow requires two specific inputs:

  • groundtruth: This input represents the actual or expected values against which the performance of the standard/chat flow will be evaluated.
  • prediction: The prediction input is derived from the outputs of another standard/chat flow. It contains the predicted values generated by the standard/chat flow, which will be compared to the groundtruth values during the evaluation process.

From the definition perspective, there is no difference compared with adding an input/output in a standard/chat flow. However when running an evaluation flow, you may need to specify the data source from both data file and flow run outputs. For more details please refer to Run and evaluate a flow.

Aggregation node

Before introducing the aggregation node, let's see what a regular node looks like, we use node grade in the example flow for instance:

yaml
- name: grade
  type: python
  source:
    type: code
    path: grade.py
  inputs:
    groundtruth: ${inputs.groundtruth}
    prediction: ${inputs.prediction}

It takes both groundtruth and prediction from the flow inputs, compare them in the source code to see if they match:

python
from promptflow.core import tool

@tool
def grade(groundtruth: str, prediction: str):
    return "Correct" if groundtruth.lower() == prediction.lower() else "Incorrect"

When it comes to an aggregation node, there are two key distinctions that set it apart from a regular node:

  1. It has an attribute aggregation set to be true.
yaml
- name: calculate_accuracy
  type: python
  source:
    type: code
    path: calculate_accuracy.py
  inputs:
    grades: ${grade.output}
  aggregation: true  # Add this attribute to make it an aggregation node
  1. Its source code accepts a List type parameter which is a collection of the previous regular node's outputs.
python
from typing import List
from promptflow.core import log_metric, tool

@tool
def calculate_accuracy(grades: List[str]):
    result = []
    for index in range(len(grades)):
        grade = grades[index]
        result.append(grade)

    # calculate accuracy for each variant
    accuracy = round((result.count("Correct") / len(result)), 2)
    log_metric("accuracy", accuracy)

    return result

The parameter grades in above function, contains all results that are produced by the regular node grade. Assuming the referred standard flow run has 3 outputs:

json
{"prediction": "App"}
{"prediction": "Channel"}
{"prediction": "Academic"}

And we provides a data file like this:

json
{"groundtruth": "App"}
{"groundtruth": "Channel"}
{"groundtruth": "Wiki"}

Then the grades value would be ["Correct", "Correct", "Incorrect"], and the final accuracy is 0.67.

This example provides a straightforward demonstration of how to evaluate the classification flow. Once you have a solid understanding of the evaluation mechanism, you can customize and design your own evaluation method to suit your specific needs.

More about the list parameter

What if the number of referred standard flow run outputs does not match the provided data file? We know that a standard flow can be executed against multiple line data and some of them could fail while others succeed. Consider the same standard flow run mentioned in above example but the 2nd line run has failed, thus we have below run outputs:

json
{"prediction": "App"}
{"prediction": "Academic"}

The promptflow flow executor has the capability to recognize the index of the referred run's outputs and extract the corresponding data from the provided data file. This means that during the execution process, even if the same data file is provided(3 lines), only the specific data mentioned below will be processed:

json
{"groundtruth": "App"}
{"groundtruth": "Wiki"}

In this case, the grades value would be ["Correct", "Incorrect"] and the accuracy is 0.5.

How to set aggregation node in VS Code Extention

How to log metrics

:::{admonition} Limitation
You can only log metrics in an aggregation node, otherwise the metric will be ignored.
:::
Promptflow supports logging and tracking experiments using log_metric function. A metric is a key-value pair that records a single float measure. In a python node, you can log a metric with below code:

python
from typing import List
from promptflow.core import log_metric, tool

@tool
def example_log_metrics(grades: List[str]):
    # this node is an aggregation node so it accepts a list of grades
    metric_key = "accuracy"
    metric_value = round((grades.count("Correct") / len(result)), 2)
    log_metric(metric_key, metric_value)

After the run is completed, you can run pf run show-metrics -n <run_name> to see the metrics.


How To Guides Develop A Dag Flow Develop Standard Flow (`docs/how-to-guides/develop-a-dag-flow/develop-standard-flow.md`)

Develop standard flow

From this document, you can learn how to develop a standard flow by writing a flow yaml from scratch. You can
find additional information about flow yaml schema in Flow YAML Schema.

Flow input data

The flow input data is the data that you want to process in your flow.
::::{tab-set}
:::{tab-item} CLI
:sync: CLI
You can add a flow input in inputs section of flow yaml.

yaml
inputs:
  url:
    type: string
    default: https://www.microsoft.com/en-us/d/xbox-wireless-controller-stellar-shift-special-edition/94fbjc7h0h6h

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
When unfolding Inputs section in the authoring page, you can set and view your flow inputs, including input schema (name and type),
and the input value.

:::

::::
For Web Classification sample as shown the screenshot above, the flow input is an url of string type.
For more input types in a python tool, please refer to Input types.

Develop the flow using different tools

In one flow, you can consume different kinds of tools. We now support built-in tool like
LLM, Python and
Prompt and
third-party tool like Serp API,
Vector Search, etc.

Add tool as your need

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
You can add a tool node in nodes section of flow yaml. For example, yaml below shows how to add a Python tool node in the flow.

yaml
nodes:
- name: fetch_text_content_from_url
  type: python
  source:
    type: code
    path: fetch_text_content_from_url.py
  inputs:
    url: ${inputs.url}

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
By selecting the tool card on the very top, you'll add a new tool node to flow.

:::

::::

Edit tool

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
You can edit the tool by simply opening the source file and making edits. For example, we provide a simple Python tool code below.

python
from promptflow.core import tool

# The inputs section will change based on the arguments of the tool function, after you save the code
# Adding type to arguments and return value will help the system show the types properly
# Please update the function name/signature per need
@tool
def my_python_tool(input1: str) -> str:
  return 'hello ' + input1

We also provide an LLM tool prompt below.

jinja
Please summarize the following text in one paragraph. 100 words.
Do not add any information that is not in the text.
Text: {{text}}
Summary:

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
When a new tool node is added to flow, it will be appended at the bottom of flatten view with a random name by default.
At the top of each tool node card, there's a toolbar for adjusting the tool node. You can move it up or down, you can delete or rename it too.
For a python tool node, you can edit the tool code by clicking the code file. For a LLM tool node, you can edit the
tool prompt by clicking the prompt file and adjust input parameters like connection, api and etc.

:::

::::

Create connection

Please refer to the Create necessary connections for details.

Before linking nodes together, you need to define and expose an interface.

Define LLM node interface

LLM node has only one output, the completion given by LLM provider.

As for inputs, we offer a templating strategy that can help you create parametric prompts that accept different input
values. Instead of fixed text, enclose your input name in {{}}, so it can be replaced on the fly. We use Jinja as our
templating language. For example:

jinja
Your task is to classify a given url into one of the following types:
Movie, App, Academic, Channel, Profile, PDF or None based on the text content information.
The classification will be based on the url, the webpage text content summary, or both.

Here are a few examples:
{% for ex in examples %}
URL: {{ex.url}}
Text content: {{ex.text_content}}
OUTPUT:
{"category": "{{ex.category}}", "evidence": "{{ex.evidence}}"}

{% endfor %}

For a given URL : {{url}}, and text content: {{text_content}}.
Classify above url to complete the category and indicate evidence.
OUTPUT:

Define Python node interface

Python node might have multiple inputs and outputs. Define inputs and outputs as shown below.
If you have multiple outputs, remember to make it a dictionary so that the downstream node can call each key separately.
For example:

python
import json
from promptflow.core import tool

@tool
def convert_to_dict(input_str: str, input_str2: str) -> dict:
    try:
        print(input_str2)
        return json.loads(input_str)
    except Exception as e:
        print("input is not valid, error: {}".format(e))
        return {"category": "None", "evidence": "None"}

After the interface is defined, you can use:

  • ${inputs.key} to link with flow input.
  • ${upstream_node_name.output} to link with single-output upstream node.
  • ${upstream_node_name.output.key} to link with multi-output upstream node.

Below are common scenarios for linking nodes together.

After you add a new LLM node and edit the prompt file like Define LLM node interface,
three inputs called url, examples and text_content are created in inputs section.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
You can link the LLM node input with flow input by ${inputs.url}.
And you can link examples to the upstream prepare_examples node and text_content to the summarize_text_content node
by ${prepare_examples.output} and ${summarize_text_content.output}.

yaml
- name: classify_with_llm
  type: llm
  source:
    type: code
    path: classify_with_llm.jinja2
  inputs:
    deployment_name: text-davinci-003
    suffix: ""
    max_tokens: 128
    temperature: 0.2
    top_p: 1
    echo: false
    presence_penalty: 0
    frequency_penalty: 0
    best_of: 1
    url: ${inputs.url}    # Link with flow input
    examples: ${prepare_examples.output} # Link LLM node with single-output upstream node
    text_content: ${summarize_text_content.output} # Link LLM node with single-output upstream node

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
In the value drop-down, select ${inputs.url}, ${prepare_examples.output} and ${summarize_text_content.output}, then
you'll see in the graph view that the newly created LLM node is linked to the flow input, upstream prepare_examples and summarize_text_content node.

:::

::::
When running the flow, the url input of the node will be replaced by flow input on the fly, and the examples and
text_content input of the node will be replaced by prepare_examples and summarize_text_content node output on the fly.

Suppose we want to link the newly created LLM node with covert_to_dict Python node whose output is a dictionary with two keys: category and evidence.
::::{tab-set}
:::{tab-item} CLI
:sync: CLI
You can link examples to the evidence output of upstream covert_to_dict node by ${convert_to_dict.output.evidence} like below:

yaml
- name: classify_with_llm
  type: llm
  source:
    type: code
    path: classify_with_llm.jinja2
  inputs:
    deployment_name: text-davinci-003
    suffix: ""
    max_tokens: 128
    temperature: 0.2
    top_p: 1
    echo: false
    presence_penalty: 0
    frequency_penalty: 0
    best_of: 1
    text_content: ${convert_to_dict.output.evidence} # Link LLM node with multi-output upstream node

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
In the value drop-down, select ${convert_to_dict.output}, then manually append evidence, then you'll see in the graph
view that the newly created LLM node is linked to the upstream convert_to_dict node.

:::
::::
When running the flow, the text_content input of the node will be replaced by evidence value from convert_to_dict node output dictionary on the fly.

After you add a new Python node and edit the code file like Define Python node interface],
two inputs called input_str and input_str2 are created in inputs section. The linkage is the same as LLM node,
using ${flow.input_name} to link with flow input or ${upstream_node_name.output} to link with upstream node.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

yaml
- name: prepare_examples
  type: python
  source:
    type: code
    path: prepare_examples.py
  inputs:
    input_str: ${inputs.url}  # Link Python node with flow input
    input_str2: ${fetch_text_content_from_url.output} # Link Python node with single-output upstream node

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

:::

::::
When running the flow, the input_str input of the node will be replaced by flow input on the fly and the input_str2
input of the node will be replaced by fetch_text_content_from_url node output dictionary on the fly.

Set flow output

When the flow is complicated, instead of checking outputs on each node, you can set flow output and check outputs of
multiple nodes in one place. Moreover, flow output helps:

  • Check bulk test results in one single table.
  • Define evaluation interface mapping.
  • Set deployment response schema.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
You can add flow outputs in outputs section of flow yaml . The linkage is the same as LLM node,
using ${convert_to_dict.output.category} to link category flow output with with category value of upstream node
convert_to_dict.

yaml
outputs:
  category:
    type: string
    reference: ${convert_to_dict.output.category}
  evidence:
    type: string
    reference: ${convert_to_dict.output.evidence}

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension
First define flow output schema, then select in drop-down the node whose output you want to set as flow output.
Since convert_to_dict has a dictionary output with two keys: category and evidence, you need to manually append
category and evidence to each. Then run flow, after a while, you can check flow output in a table.

:::

::::


How To Guides Develop A Dag Flow Init And Test A Flow (`docs/how-to-guides/develop-a-dag-flow/init-and-test-a-flow.md`)

Initialize and test a flow

From this document, customer can initialize a flow and test it.

Initialize flow

Creating a flow folder with code/prompts and yaml definitions of the flow.

Initialize flow from scratch

Promptflow can create three types of flow folder:

  • standard: Basic structure of flow folder.
  • chat: Chat flow is designed for conversational application development, building upon the capabilities of standard flow and providing enhanced support for chat inputs/outputs and chat history management.
  • evaluation: Evaluation flows are special types of flows that assess how well the outputs of a flow align with specific criteria and goals.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
# Create a flow
pf flow init --flow <flow-name>

# Create a chat flow
pf flow init --flow <flow-name> --type chat

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

Use VS Code explorer pane > directory icon > right click > the "New flow in this directory" action. Follow the popped out dialog to initialize your flow in the target folder.

Alternatively, you can use the "Create new flow" action on the prompt flow pane > quick access section to create a new flow

:::

::::

Structure of flow folder:

  • flow.dag.yaml: The flow definition with inputs/outputs, nodes, tools and variants for authoring purpose.
  • .promptflow/flow.tools.json: It contains tools meta referenced in flow.dag.yaml.
  • Source code files (.py, .jinja2): User managed, the code scripts referenced by tools.
  • requirements.txt: Python package dependencies for this flow.

Create from existing code

Customer needs to pass the path of tool script to entry, and also needs to pass in the promptflow template dict to prompt-template, which the key is the input name of the tool and the value is the path to the promptflow template.
Promptflow CLI can generate the yaml definitions needed for prompt flow from the existing folder, using the tools script and prompt templates.

bash
# Create a flow in existing folder
pf flow init --flow <flow-name> --entry <tool-script-path> --function <tool-function-name> --prompt-template <prompt-param-name>=<prompt-tempate-path>

Take customer-intent-extraction for example, which demonstrating how to convert a langchain code into a prompt flow.

In this case, promptflow CLI generates flow.dag.yaml, .promptflow/flow.tools.json and extract_intent_tool.py, it is a python tool in the flow.

Test a flow

:::{admonition} Note
Testing flow will NOT create a batch run record, therefore it's unable to use commands like pf run show-details to get the run information. If you want to persist the run record, see Run and evaluate a flow
:::

Promptflow also provides ways to test the initialized flow or flow node. It will help you quickly test your flow.

Visual editor on the VS Code for prompt flow.

::::{tab-set}
:::{tab-item} VS Code Extension
:sync: VS Code Extension

Open the flow.dag.yaml file of your flow. On the top of the yaml editor you can find the "Visual editor" action. Use it to open the Visual editor with GUI support.

:::

::::

Test flow

Customer can use CLI or VS Code extension to test the flow.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
# Test flow
pf flow test --flow <flow-name>

# Test flow with specified variant
pf flow test --flow <flow-name> --variant '${<node-name>.<variant-name>}'

The log and result of flow test will be displayed in the terminal.

Promptflow CLI will generate test logs and outputs in .promptflow:

  • flow.detail.json: Defails info of flow test, include the result of each node.
  • flow.log: The log of flow test.
  • flow.output.json: The result of flow test.

:::

:::{tab-item} SDK
:sync: SDK

The return value of test function is the flow outputs.

python
from promptflow.client import PFClient

pf_client = PFClient()

# Test flow
inputs = {"<flow_input_name>": "<flow_input_value>"}  # The inputs of the flow.
flow_result = pf_client.test(flow="<flow_folder_path>", inputs=inputs)
print(f"Flow outputs: {flow_result}")

The log and result of flow test will be displayed in the terminal.

Promptflow CLI will generate test logs and outputs in .promptflow:

  • flow.detail.json: Defails info of flow test, include the result of each node.
  • flow.log: The log of flow test.
  • flow.output.json: The result of flow test.

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

You can use the action either on the default yaml editor or the visual editor to trigger flow test. See the snapshots below:

:::

::::

Test a single node in the flow

Customer can test a single python node in the flow. It will use customer provides date or the default value of the node as input. It will only use customer specified node to execute with the input.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Customer can execute this command to test the flow.

bash
# Test flow node
pf flow test --flow <flow-name> --node <node-name>

The log and result of flow node test will be displayed in the terminal. And the details of node test will generated to .promptflow/flow-<node-name>.node.detail.json.

:::

:::{tab-item} SDK
:sync: SDK

Customer can execute this command to test the flow. The return value of test function is the node outputs.

python
from promptflow.client import PFClient

pf_client = PFClient()

# Test not iun the flow
inputs = {<node_input_name>: <node_input_value>}  # The inputs of the node.
node_result = pf_client.test(flow=<flow_folder_path>, inputs=inputs, node=<node_name>)
print(f"Node outputs: {node_result}")

The log and result of flow node test will be displayed in the terminal. And the details of node test will generated to .promptflow/flow-<node-name>.node.detail.json.

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

The prompt flow extension provides inline actions in both default yaml editor and visual editor to trigger single node runs.

:::

::::

Test with interactive mode

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Promptflow CLI provides a way to start an interactive chat session for chat flow. Customer can use below command to start an interactive chat session:

bash
# Chat in the flow
pf flow test --flow <flow-name> --interactive

After executing this command, customer can interact with the chat flow in the terminal. Customer can press Enter to send the message to chat flow. And customer can quit with ctrl+C.
Promptflow CLI will distinguish the output of different roles by color, User input, Bot output, Flow script output, Node output.

Using this chat flow to show how to use interactive mode.

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

If a flow contains chat inputs or chat outputs in the flow interface, there will be a selection when triggering flow test. You can select the interactive mode if you want to.

:::

::::

When the LLM node in the chat flow that is connected to the flow output, Promptflow SDK streams the results of the LLM node.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
The flow result will be streamed in the terminal as shown below.

:::

:::{tab-item} SDK
:sync: SDK

The LLM node return value of test function is a generator, you can consume the result by this way:

python
from promptflow.client import PFClient

pf_client = PFClient()

# Test flow
inputs = {"<flow_input_name>": "<flow_input_value>"}  # The inputs of the flow.
flow_result = pf_client.test(flow="<flow_folder_path>", inputs=inputs)
for item in flow_result["<LLM_node_output_name>"]:
    print(item)

:::

::::

Debug a single node in the flow

Customer can debug a single python node in VScode by the extension.

::::{tab-set}
:::{tab-item} VS Code Extension
:sync: VS Code Extension

Break points and debugging functionalities for the Python steps in your flow. Just set the break points and use the debug actions on either default yaml editor or visual editor.

:::

::::

Next steps


How To Guides Develop A Dag Flow Process Image In Flow (`docs/how-to-guides/develop-a-dag-flow/process-image-in-flow.md`)

Process image in flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

PromptFlow defines a contract to represent image data.

Data class

promptflow.contracts.multimedia.Image
Image class is a subclass of bytes, thus you can access the binary data by directly using the object. It has an extra attribute source_url to store the origin url of the image, which would be useful if you want to pass the url instead of content of image to APIs like GPT-4V model.

Data type in flow input

Set the type of flow input to image and promptflow will treat it as an image.

Reference image in prompt template

In prompt templates that support image (e.g. in OpenAI GPT-4V tool), using markdown syntax to denote that a template input is an image: ``. In this case, test_image will be substituted with base64 or source_url (if set) before sending to LLM model.

Serialization/Deserialization

Promptflow uses a special dict to represent image.
{"data:image/<mime-type>;<representation>": "<value>"}

  • <mime-type> can be html standard mime image types. Setting it to specific type can help previewing the image correctly, or it can be * for unknown type.

  • <representation> is the image serialized representation, there are 3 supported types:

    • url

      It can point to a public accessable web url. E.g.

      {"data:image/png;url": "https://developer.microsoft.com/_devcom/images/logo-ms-social.png"}

    • base64

      It can be the base64 encoding of the image. E.g.

      {"data:image/png;base64": "iVBORw0KGgoAAAANSUhEUgAAAGQAAABLAQMAAAC81rD0AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEUAAP7////DYP5JAAAAAWJLR0QB/wIt3gAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB+QIGBcKN7/nP/UAAAASSURBVDjLY2AYBaNgFIwCdAAABBoAAaNglfsAAAAZdEVYdGNvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVDnr0DLAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIwLTA4LTI0VDIzOjEwOjU1KzAzOjAwkHdeuQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMC0wOC0yNFQyMzoxMDo1NSswMzowMOEq5gUAAAAASUVORK5CYII="}

    • path

      It can reference an image file on local disk. Both absolute path and relative path are supported, but in the cases where the serialized image representation is stored in a file, relative to the containing folder of that file is recommended, as in the case of flow IO data. E.g.

      {"data:image/png;path": "./my-image.png"}

Please note that path representation is not supported in Deployment scenario.

Batch Input data

Batch input data containing image can be of 2 formats:

  1. The same jsonl format of regular batch input, except that some column may be seriliazed image data or composite data type (dict/list) containing images. The serialized images can only be Url or Base64. E.g.
    json
    {"question": "How many colors are there in the image?", "input_image": {"data:image/png;url": "https://developer.microsoft.com/_devcom/images/logo-ms-social.png"}}
    {"question": "What's this image about?", "input_image": {"data:image/png;url": "https://developer.microsoft.com/_devcom/images/404.png"}}
  2. A folder containing a jsonl file under root path, which contains serialized image in File Reference format. The referenced file are stored in the folder and their relative path to the root path is used as path in the file reference. Here is a sample batch input, note that the name of input.jsonl is arbitrary as long as it's a jsonl file:
    text
    BatchInputFolder
    |----input.jsonl
    |----image1.png
    |----image2.png
    Content of input.jsonl
    json
    {"question": "How many colors are there in the image?", "input_image": {"data:image/png;path": "image1.png"}}
    {"question": "What's this image about?", "input_image": {"data:image/png;path": "image2.png"}}

How To Guides Develop A Dag Flow Quick Start (`docs/how-to-guides/develop-a-dag-flow/quick-start.md`)

Quick start

This guide will walk you through the fist step using of prompt flow code-first experience.

Prerequisite - To make the most of this tutorial, you'll need:

  • Know how to program with Python :)
  • A basic understanding of Machine Learning can be beneficial, but it's not mandatory.

Learning Objectives - Upon completing this tutorial, you should learn how to:

  • Setup your python environment to run prompt flow
  • Clone a sample flow & understand what's a flow
  • Understand how to edit the flow using visual editor or yaml
  • Test the flow using your favorite experience: CLI, SDK or VS Code Extension.

Set up your dev environment

  1. A python environment with version python=3.9 or higher version like 3.10. It's recommended to use python environment manager miniconda. After you have installed miniconda, run below commands to create a python environment:
bash
conda create --name pf python=3.9
conda activate pf
  1. Install promptflow and promptflow-tools.
sh
pip install promptflow promptflow-tools
  1. Check the installation.
bash
# should print promptflow version, e.g. "0.1.0b3"
pf -v

Understand what's a flow

A flow, represented as a YAML file, is a DAG of functions, which is connected via input/output dependencies, and executed based on the topology by prompt flow executor. See Flows for more details.

Get the flow sample

Clone the sample repo and check flows in folder examples/flows.

bash
git clone https://github.com/microsoft/promptflow.git

Understand flow directory

The sample used in this tutorial is the web-classification flow, which categorizes URLs into several predefined classes. Classification is a traditional machine learning task, and this sample illustrates how to perform classification using GPT and prompts.

bash
cd promptflow/examples/flows/standard/web-classification

A flow directory is a directory that contains all contents of a flow. Structure of flow folder:

  • flow.dag.yaml: The flow definition with inputs/outputs, nodes, tools and variants for authoring purpose.
  • .promptflow/flow.tools.json: It contains tools meta referenced in flow.dag.yaml.
  • Source code files (.py, .jinja2): User managed, the code scripts referenced by tools.
  • requirements.txt: Python package dependencies for this flow.

In order to run this specific flow, you need to install its requirements first.

sh
pip install -r requirements.txt

Understand the flow yaml

The entry file of a flow directory is flow.dag.yaml which describes the DAG(Directed Acyclic Graph) of a flow. Below is a sample of flow DAG:

This graph is rendered by VS Code extension which will be introduced in the next section.

Using VS Code Extension to visualize the flow

Note: Prompt flow VS Code Extension is highly recommended for flow development and debugging.

  1. Prerequisites for VS Code extension.

  2. Install Prompt flow for VS Code extension

  3. Select python interpreter

  4. Open dag in vscode. You can open the flow.dag.yaml as yaml file, or you can also open it in visual editor.

Develop and test your flow

How to edit the flow

To test your flow with varying input data, you have the option to modify the default input. If you are well-versed with the structure, you may also add or remove nodes to alter the flow's arrangement.

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs:
  url:
    type: string
    # change the default value of input url here
    default: https://play.google.com/store/apps/details?id=com.twitter.android
...

See more details of this topic in Develop a flow.

Create necessary connections

:::{note}
If you are using WSL or other OS without default keyring storage backend, you may encounter StoreConnectionEncryptionKeyError, please refer to FAQ for the solutions.
:::

The connection helps securely store and manage secret keys or other sensitive credentials required for interacting with LLM and other external tools for example Azure Content Safety.

The sample flow web-classification uses connection open_ai_connection inside, e.g. classify_with_llm node needs to talk to llm using the connection.

We need to set up the connection if we haven't added it before. Once created, the connection will be stored in local db and can be used in any flow.

::::{tab-set}

:::{tab-item} CLI
:sync: CLI

Firstly we need a connection yaml file connection.yaml:

If you are using Azure OpenAI, prepare your resource follow with this instruction and get your api_key if you don't have one.

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/AzureOpenAIConnection.schema.json
name: open_ai_connection
type: azure_open_ai
api_key: <test_key>
api_base: <test_base>
api_type: azure
api_version: <test_version>

If you are using OpenAI, sign up account via OpenAI website, login and find personal API key, then use this yaml:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/OpenAIConnection.schema.json
name: open_ai_connection
type: open_ai
api_key: "<user-input>"
organization: "" # optional

Then we can use CLI command to create the connection.

sh
pf connection create -f connection.yaml

More command details can be found in CLI reference.

:::

:::{tab-item} SDK
:sync: SDK

In SDK, connections can be created and managed with PFClient.

python
from promptflow.client import PFClient
from promptflow.entities import AzureOpenAIConnection

# PFClient can help manage your runs and connections.
pf = PFClient()

try:
    conn_name = "open_ai_connection"
    conn = pf.connections.get(name=conn_name)
    print("using existing connection")
except:
    connection = AzureOpenAIConnection(
        name=conn_name,
        api_key="<test_key>",
        api_base="<test_base>",
        api_type="azure",
        api_version="<test_version>",
    )

    # use this if you have an existing OpenAI account
    # from promptflow.entities import OpenAIConnection
    # connection = OpenAIConnection(
    #     name=conn_name,
    #     api_key="<user-input>",
    # )

    conn = pf.connections.create_or_update(connection)
    print("successfully created connection")

print(conn)

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

  1. Click the promptflow icon to enter promptflow control panel

  2. Create your connection.

:::

::::

Learn more on more actions like delete connection in: Manage connections.

Test the flow

:::{admonition} Note
Testing flow will NOT create a batch run record, therefore it's unable to use commands like pf run show-details to get the run information. If you want to persist the run record, see Run and evaluate a flow
:::

Assuming you are in working directory promptflow/examples/flows/standard/

::::{tab-set}

:::{tab-item} CLI
:sync: CLI

Change the default input to the value you want to test.

sh
pf flow test --flow web-classification  # "web-classification" is the directory name

:::

:::{tab-item} SDK
:sync: SDK

The return value of test function is the flow/node outputs.

python
from promptflow.client import PFClient

pf = PFClient()

flow_path = "web-classification"  # "web-classification" is the directory name

# Test flow
flow_inputs = {"url": "https://www.youtube.com/watch?v=o5ZQyXaAv1g", "answer": "Channel", "evidence": "Url"}  # The inputs of the flow.
flow_result = pf.test(flow=flow_path, inputs=flow_inputs)
print(f"Flow outputs: {flow_result}")

# Test node in the flow
node_name = "fetch_text_content_from_url"  # The node name in the flow.
node_inputs = {"url": "https://www.youtube.com/watch?v=o5ZQyXaAv1g"}  # The inputs of the node.
node_result = pf.test(flow=flow_path, inputs=node_inputs, node=node_name)
print(f"Node outputs: {node_result}")

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

Use the code lens action on the top of the yaml editor to trigger flow test

Click the run flow button on the top of the visual editor to trigger flow test.

:::

::::

See more details of this topic in Initialize and test a flow.

Next steps

Learn more on how to:

And you can also check our examples, especially:

  • Getting started with prompt flow: the notebook covering the python sdk experience for sample introduced in this doc.
  • Tutorial: Chat with PDF: An end-to-end tutorial on how to build a high quality chat application with prompt flow, including flow development and evaluation with metrics.

How To Guides Develop A Dag Flow Referencing External Files Or Folders In A Flow (`docs/how-to-guides/develop-a-dag-flow/referencing-external-files-or-folders-in-a-flow.md`)

Referencing external files/folders in a flow

Sometimes, pre-existing code assets are essential for the flow reference. In most cases, you can accomplish this by importing a Python package into your flow. However, if a Python package is not available or it is heavy to create a package, you can still reference external files or folders located outside of the current flow folder by using our additional includes feature in your flow configuration.

This feature provides an efficient mechanism to list relative file or folder paths that are outside of the flow folder, integrating them seamlessly into your flow.dag.yaml. For example:

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

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

Just as with the common definition of the tool node entry, you can define the tool node entry in the flow.dag.yaml using only the file name, eliminating the need to specify the relative path again. For example:

yaml
nodes:
- name: fetch_text_content_from_url
  type: python
  source:
    type: code
    path: fetch_text_content_from_url.py
  inputs:
    url: ${inputs.url}
- name: summarize_text_content
  use_variants: true
- name: prepare_examples
  type: python
  source:
    type: code
    path: prepare_examples.py
  inputs: {}

The entry file "fetch_text_content_from_url.py" of the tool node "fetch_text_content_from_url" is located in "../web-classification/fetch_text_content_from_url.py", as specified in the additional_includes field. The same applies to the "summarize_text_content" tool nodes.

Note:

  1. If you have two files with the same name located in different folders specified in the additional_includes field, and the file name is also specified as the entry of a tool node, the system will reference the last one it encounters in the additional_includes field.
  1. If you have a file in the flow folder with the same name as a file specified in the additional_includes field, the system will prioritize the file listed in the additional_includes field.
    Take the following YAML structure as an example:
yaml
additional_includes:
- ../web-classification/prepare_examples.py
- ../tmp/prepare_examples.py
...
nodes:
- name: summarize_text_content
  use_variants: true
- name: prepare_examples
  type: python
  source:
    type: code
    path: prepare_examples.py
  inputs: {}

In this case, the system will use "../tmp/prepare_examples.py" as the entry file for the tool node "prepare_examples". Even if there is a file named "prepare_examples.py" in the flow folder, the system will still use the file "../tmp/prepare_examples.py" specified in the additional_includes field.

Tips:
The additional includes feature can significantly streamline your workflow by eliminating the need to manually handle these references.

  1. To get a hands-on experience with this feature, practice with our sample flow-with-additional-includes.
  2. You can learn more about How the 'additional includes' flow operates during the transition to the cloud.

How To Guides Develop A Flex Flow Class Based Flow (`docs/how-to-guides/develop-a-flex-flow/class-based-flow.md`)

Class based flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

When user need to persist objects (like connection) in memory during multiple rounds of flow runs, they can write a callable class as flow entry and put persist params in __init__ method.

If user need to log metrics on batch run outputs, they can add an __aggregate__ method and it will be scheduled after batch run finishes.
The __aggregate__ method should only contain 1 params which is list of batch run results.

See connection support & aggregation support for more details.

Class as a flow

Assume we have a file flow_entry.py:

python
class Reply(TypedDict):
    output: str

class MyFlow:
    def __init__(self, model_config: AzureOpenAIModelConfiguration, flow_config: dict):
      """Flow initialization logic goes here."""
      self.model_config = model_config
      self.flow_config = flow_config

    def __call__(question: str) -> Reply:
      """Flow execution logic goes here."""
      return Reply(output=output)

    def __aggregate__(self, line_results: List[str]) -> dict:
      """Aggregation logic goes here. Return key-value pair as metrics."""
      return {"key": val}

Flow test

Test with original code

Since flow's definition is function/callable class. We recommend user directly run it like running other scripts:

python
class MyFlow:
    pass
if __name__ == "__main__":
    flow = MyFlow(model_config, flow_config)
    output = flow(question)
    metrics = flow.__aggregate__([output])
    # check metrics here

Test via function call

It's also supported to convert your class entry to a flow and test with prompt flow's ability.

You can test with the following CLI:

bash
# flow entry syntax: path.to.module:ClassName
pf flow test --flow flow_entry:MyFlow --inputs question="What's the capital of France?" --init init.json

Note: currently this command will generate a flow.flex.yaml in your working directory. Which will become the flow's entry.

Check out a full example here: basic-chat

Chat with a flow

Chat with flow in CLI is supported:

bash
pf flow test --flow flow_entry:MyFlow --inputs inputs.json --init init.json --ui

Check here for more information.

Batch run

User can also batch run a flow.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
pf run create --flow "path.to.module:ClassName" --data "./data.jsonl"

:::

:::{tab-item} SDK
:sync: SDK

python
# user can also directly use entry in `flow` param for batch run
pf.run(flow="path.to.module:ClassName", init="./init.jsonl", data="./data.jsonl")

:::
::::

Or directly run the imported flow class or flow instance.

python
from promptflow.core import AzureOpenAIModelConfiguration


class MyFlow:
    pass

config = AzureOpenAIModelConfiguration(
  azure_deployment="my_deployment",
  # connection and api_key configs are exclusive
  connection="my_aoai_connection",
  api_key="actual_key",
)
pf.run(flow=MyFlow, init={"model_config": config, "flow_config": {}}, data="./data.jsonl")
# or
flow_obj = MyFlow(model_config=config, flow_config={})
pf.run(flow=flow_obj, data="./data.jsonl")

Learn more on this topic on Run and evaluate a flow

Define a flow yaml

User can write a YAML file with name flow.flex.yaml manually or save a function/callable entry to YAML file.
This is required for advanced scenario like deployment or run in cloud.
A flow YAML may look like this:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
entry: path.to.module:ClassName

Batch run with YAML

User can batch run a flow. Flow init function's param is supported by init parameter.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

User need to write an JSON file as init's value since it's hard to write model config in command line.

json
{
    "model_config": {
        "azure_endpoint": "my_endpoint",
        "azure_deployment": "my_deployment",
        "api_key": "actual_api_key"
    },
    "flow_config": {}
}
bash
pf run create --flow "./flow.flex.yaml" --data "./data.jsonl" --init init.json

:::

:::{tab-item} SDK
:sync: SDK

python
pf = PFClient()

config = AzureOpenAIModelConfiguration(
  azure_deployment="my_deployment",
  api_key="actual_key"
)
# if init's value is not json serializable, raise user error
pf.run(flow="./flow.flex.yaml", init={"model_config": config, "flow_config": {}}, data="./data.jsonl")

# when submit to cloud, user can only use connection
# in runtime executor will resolve connection in AzureOpenAIModelConfiguration and set connection's fields to ModelConfig: equal to original ModelConfiguration.from_connection()
config = AzureOpenAIModelConfiguration(
  azure_deployment="my_embedding_deployment",
  connection="my-aoai-connection",
) 
pfazure.run(flow="./flow.flex.yaml", init={"model_config": config, "flow_config": {}}, data="./data.jsonl")

:::
::::

Deploy a flow

User can serve a flow. Flow init function's param is supported by init parameter.
The flow should have complete init/inputs/outputs specification in YAML to make sure serving swagger can be generated.

User need to write an JSON file as init's value since it's hard to write model config in command line.

json
{
    "model_config": {
        "azure_endpoint": "my_endpoint",
        "azure_deployment": "my_deployment",
        "api_key": "actual_api_key"
    },
    "flow_config": {}
}
bash
# user can only pass model config by file 
pf flow serve --source "./"  --port 8088 --host localhost --init path/to/init.json

Learn more: Deploy a flow.

Aggregation support

Aggregation support is introduce to help user calculate metrics.

python
class MyFlow:
    def __call__(text: str) -> str:
      """Flow execution logic goes here."""
      pass

    # will only execute once after batch run finished.
    # the processed_results will be list of __call__'s output and we will log the return value as metrics automatically.
    def __aggregate__(self, processed_results: List[str]) -> dict:
        for element in processed_results:
            # If __call__'s output is primitive type, element will be primitive type.
            # If __call__'s output is dataclass, element will be a dictionary, but can access it's attribute with `element.attribute_name`
            # For other cases, it's recommended to access by key `element["attribute_name"]`

Note:

There's several limitations on aggregation support:

  • The aggregation function will only execute in batch run.
  • Only 1 hard coded __aggregate__ function is supported.
  • The __aggregate__ will only be passed 1 positional arguments when executing.
  • The aggregation function’s input will be flow run’s outputs list.
    • Each element inside processed_results passed passed inside __aggregate__ function is not same object with each line's __call__ returns.
    • The reconstructed element is a dictionary which supports 1 layer attribute access. But it's recommended to access them by key. See the above example for usage.
  • If aggregation function accept more than 1 arguments, raise error in submission phase.

Next steps


How To Guides Develop A Flex Flow Connection Support (`docs/how-to-guides/develop-a-flex-flow/connection-support.md`)

Use connections in flow

The connection helps securely store and manage secret keys or other sensitive credentials required for interacting with LLM and other external tools for example Azure Content Safety.
The following usage of connections is supported in prompt flow.

Model config in `__init__`

Just like example in class based flow batch run, it's supported to reference connection in ModelConfig.
Reference here for more information about ModelConfig.
And connection will be resolved and flatten connection's fields to ModelConfig.
Note: Currently model config only support OpenAI and AzureOpenAI connection.
For custom connection, please use connection in init.

Connection in `__init__`

It's also supported to directly pass connection by name in __init__.

python
class MyFlow:
    def __init__(self, my_connection: AzureOpenAIConnection):
        pass

Note:

  • Union of connection types(Union[OpenAIConnection, AzureOpenAIConnection]) is not supported.

Batch run with connection

User can pass connection name to connection field in init.

In local, the connection name will be replaced with local connection object in execution time.
In cloud, the connection name will be replaced with workspace's connection object in execution time.

python
# local connection "my_connection"'s instance will be passed to `__init__`
pf.run(flow="./flow.flex.yaml", init={"connection": "my_connection"}, data="./data.jsonl")
# cloud connection "my_cloud_connection"'s instance will be passed to `__init__`
pfazure.run(flow="./flow.flex.yaml", init={"connection": "my_cloud_connection"}, data="./data.jsonl")

Environment variable connections

If flow YAML has environment_variables and it's value is a connection reference like this:

yaml
environment_variables:
  AZURE_OPENAI_API_KEY: ${open_ai_connection.api_key}
  AZURE_OPENAI_ENDPOINT: ${open_ai_connection.api_base}

The environment variable's value will be resolved to actual value in runtime.
If the connection not exist (in local or cloud), connection not found error will be raised.

Note: User can override the environment_variables with existing environment variable keys in flow.flex.yaml:

bash
pf run create --flow . --data ./data.jsonl --environment-variables AZURE_OPENAI_API_KEY='${new_connection.api_key}' AZURE_OPENAI_ENDPOINT='my_endpoint'

Overriding with environment variable names which not exist in flow.flex.yaml is not supported.
Which means if user added environment variables which does not exist in flow.flex.yaml in runtime, it's value won't be resolved.

For example,

bash
pf run create --flow . --data ./data.jsonl --environment-variables NEW_API_KEY='${my_new_connection.api_key}'

The NEW_API_KEY's value won't be resolved to connection's API key.


How To Guides Develop A Flex Flow Function Based Flow (`docs/how-to-guides/develop-a-flex-flow/function-based-flow.md`)

Function based flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

User can directly use a function as flow entry.

Function as a flow

Assume we have a file flow_entry.py:

python
from promptflow.tracing import trace

class Reply(TypedDict):
    output: str

@trace
def my_flow(question: str) -> Reply:
    # flow logic goes here
    pass

Note function decorated with @trace will emit trace can be viewed in UI provided by PromptFlow. Check here for more information.

Flow test

Test via function call

Since flow's definition is normal python function/callable class. We recommend user directly run it like running other scripts:

python
from flow_entry import my_flow

if __name__ == "__main__":
    output = my_flow(question="What's the capital of France?")
    print(output)

Convert to a flow and test

It's also supported to convert your function entry to a flow and test with prompt flow's ability.

You can test with the following CLI:

bash
# flow entry syntax: path.to.module:function_name
pf flow test --flow flow_entry:my_flow --inputs question="What's the capital of France?"

Note: currently this command will generate a flow.flex.yaml in your working directory. Which will become the flow's entry.

Check out a full example here: basic

Chat with a flow

Start a UI to chat with a flow:

bash
pf flow test --flow flow_entry:my_flow --inputs question="What's the capital of France?" --ui

Check here for more information.

Batch run

User can also batch run a flow.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
pf run create --flow "path.to.module:function_name" --data "./data.jsonl"

:::

:::{tab-item} SDK
:sync: SDK

python
from path.to.module import my_flow
# Note directly run function in `pf.run` is only supported in local PFClient for now 
pf.run(flow=my_flow, data="./data.jsonl")

# user can also directly use entry in `flow` param for batch run
pf.run(flow="path.to.module:function_name", data="./data.jsonl")

:::
::::

Learn more on this topic on Run and evaluate a flow

Define a flow yaml

User can write a YAML file with name flow.flex.yaml manually or save a function/callable entry to YAML file.
This is required for advanced scenario like deployment or run in cloud.
A flow YAML may look like this:

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
entry: path.to.module:function_name
sample:
    inputs:
        question: "what's the capital of France?"

Batch run with YAML

User can batch run a flow with YAML.

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
# against flow file
pf run create --flow "path/to/flow/flow.flex.yaml" --data "./data.jsonl"
# against a folder if it has a flow.flex.yaml file
pf run create --flow "path/to/flow" --data "./data.jsonl"

:::

:::{tab-item} SDK
:sync: SDK

python
pf = PFClient()
pf.run(flow="./flow.flex.yaml", data="./data.jsonl")

:::
::::

Deploy a flow

User can serve a flow as a http endpoint locally or deploy it to multiple platforms.

bash
# serve locally from a folder if it has a flow.flex.yaml file
pf flow serve --source "path/to/flow/dir"  --port 8088 --host localhost

# serve locally from certain file
pf flow serve --source "./flow.flex.yaml"  --port 8088 --host localhost

Learn more: Deploy a flow.

Next steps


How To Guides Develop A Flex Flow Input Output Format (`docs/how-to-guides/develop-a-flex-flow/input-output-format.md`)

Input output format

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Supported types

Promptflow officially support below types in flow.

  • Inputs: primitive types(int, float, bool, str), dict, TypedDict, list

  • Outputs: primitive types(int, float, bool, str), dict, TypedDict, dataclass, list

  • Init: primitive types(int, float, bool, str), Connection(including custom connections), ModelConfiguration, TypedDict, list

If user has non-supported types in code/YAML, validation error will be raised.

YAML support

Here's a mapping from python types to YAML types:

Python Type YAML type Description
int int Integer type
float double Double type
bool bool Boolean type
str string String type
list list List type
dict object Dictionary type
TypedDict object Typed dictionary type
dataclass object Data class type
CustomConnection Connection Connection type, will be handled specially
OpenAIModelConfiguration OpenAIModelConfiguration Model configuration type, will be handled specially
AzureOpenAIModelConfiguration AzureOpenAIModelConfiguration Model configuration type, will be handled specially

Here's an sample YAML for above supported types.

yaml
inputs:
  int_input:
    type: int
  float_input:
    type: double
  bool_input:
    type: bool
  string_input:
    type: string
  dict_input:
    type: object
  list_input:
    type: list
outputs:
  int_output:
    type: int
  float_output:
    type: double
  bool_output:
    type: bool
  string_output:
    type: string
  dict_output:
    type: object
  list_output:
    type: list
init:
  int_init:
    type: int
  float_init:
    type: double
  bool_init:
    type: bool
  string_init:
    type: string
  open_ai_connection:
    type: OpenAIConnection
  azure_open_ai_connection:
    type: AzureOpenAIConnection
  custom_connection:
    type: CustomConnection
  open_ai_model_config:
    type: OpenAIModelConfiguration
  azure_open_ai_model_config:
    type: AzureOpenAIModelConfiguration

Unsupported type sample

python
# using unsupported types in flow will fail with validation error
class MyOwnClass:
  pass

class MyFlow:
    # not supported
    def __init__(self, my_own_obj: MyOwnClass):
        pass

# not supported
def my_flow(my_own_obj: MyOwnClass):
    pass

Sample validation error: "The input 'my_own_obj' is of a complex python type. Please use a dict instead."

Stream

Stream is supported in flow, you just need to return a generator type in your function.
Reference openai doc on how to do it using plain python code: how_to_stream_completions.

Reference this flow sample for details.


How To Guides Develop A Flex Flow Model Config (`docs/how-to-guides/develop-a-flex-flow/model-config.md`)

Model Configuration

Tailoring your AI applications to use specific models with desired parameters is now easier than ever with the Promptflow SDK's new Model Configuration feature. Whether you're engaging with chatbots, generating text, or building complex AI workflows, our unified configuration approach allows you to set up and switch between models from OpenAI, AzureOpenAI seamlessly.

Model Configuration at a Glance

We've designed a set of classes that cater to various scenarios, each with a straightforward setup process. Here's how you can configure models for different services:

`AzureOpenAIModelConfiguration`

The AzureOpenAIModelConfiguration class lets you connect to Azure's AI services with minimal hassle. Just provide your endpoint, deployment, and optional authentication details, and you're good to go.
Reference here for it's defintion.

`OpenAIModelConfiguration`

The OpenAIModelConfiguration class is tailored for direct OpenAI integration. Specify your API key, the model you want to use, and any additional parameters.
Reference here for it's definition.


How To Guides Develop A Prompty Prompty Output Format (`docs/how-to-guides/develop-a-prompty/prompty-output-format.md`)

Prompty output format

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

In this doc, you will learn:

  • Understand how to handle output format of prompty like: text, json_object.
  • Understand how to consume stream output of prompty

Formatting prompty output

Text output

By default, prompty returns the message from the first choice in the response. Below is an example of how to format a prompty for text output:

yaml
---
name: Text Format Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    connection: open_ai_connection
    azure_deployment: gpt-35-turbo-0125
  parameters:
    max_tokens: 128
    temperature: 0.2
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: what is the meaning of life?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly,
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
{{question}}

The output of the prompty is a string content, as shown in the example below:

text
Ah, the age-old question about the meaning of life! πŸŒπŸ€” The meaning of life is a deeply philosophical and subjective topic. Different people have different perspectives on it. Some believe that the meaning of life is to seek happiness and fulfillment, while others find meaning in personal relationships, accomplishments, or spiritual beliefs. Ultimately, it's up to each individual to explore and discover their own purpose and meaning in life. 🌟

Json object output

Prompty can return the content of the first choice as a dictionary object when the following conditions are met:

  • The response_format is defined as type: json_object in the parameters
  • The template specifies the JSON format for the return value.

Note: json_object response_format is compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than gpt-3.5-turbo-1106. For more details, refer to this document.

Here’s how to configure a prompty for JSON object output:

yaml
---
name: Json Format Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    azure_deployment: gpt-35-turbo-0125
    connection: open_ai_connection
  parameters:
    max_tokens: 128
    temperature: 0.2
    response_format:
      type: json_object
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: what is the meaning of life?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly. Your structured response. Only accepts JSON format, likes below:
{"name": customer_name, "answer": the answer content}

# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
{{question}}

The output of the prompty is a JSON object containing the content of the first choice:

json
{
    "name": "John",
    "answer": "The meaning of life is a philosophical question that varies depending on individual beliefs and perspectives."
}

Users can also specify the fields to be returned by configuring the output section:

yaml
---
name: Json Format Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    azure_deployment: gpt-35-turbo-0125
    connection: open_ai_connection
  parameters:
    max_tokens: 128
    temperature: 0.2
    response_format:
      type: json_object
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
outputs:
  answer:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: what is the meaning of life?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly. Your structured response. Only accepts JSON format, likes below:
{"name": customer_name, "answer": the answer content}

# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
{{question}}

Prompty will then return the outputs as specified by the user:

json
{
  "answer": "The meaning of life is a philosophical question that varies depending on individual beliefs and perspectives."
}

All choices

In certain scenarios, users may require access to the original response from the language model (LLM) for further processing. This can be achieved by setting response=all, which allows retrieval of the original LLM response. For detailed information, please refer to the LLM response.

yaml
---
name: All Choices Text Format Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    connection: open_ai_connection
    azure_deployment: gpt-35-turbo-0125
  parameters:
    max_tokens: 128
    temperature: 0.2
    n: 3
  response: all
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: what is the meaning of life?
---
system:
You are an AI assistant who helps people find information.
As the assistant, you answer questions briefly, succinctly,
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping {{first_name}} {{last_name}} to find answers to their questions.
Use their name to address them in your responses.

user:
{{question}}

Streaming output

For prompty configurations where the response_format is text, setting stream=true in the parameters will result in the Promptflow SDK returning a generator. Each item from the generator represents the content of a chunk.

Here’s how to configure a prompty for streaming text output:

yaml
---
name: Stream Mode Text Format Prompt
description: A basic prompt that uses the GPT-3 chat API to answer questions
model:
  api: chat
  configuration:
    type: azure_openai
    connection: open_ai_connection
    azure_deployment: gpt-35-turbo-0125
  parameters:
    max_tokens: 512
    temperature: 0.2
    stream: true
inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
sample:
  first_name: John
  last_name: Doe
  question: What's the steps to get rich?
---
system:
You are an AI assistant who helps people find information.
and in a personable manner using markdown and even add some personal flair with appropriate emojis.

# Safety
- You **should always** reference factual statements to search results based on [relevant documents]
- Search results based on [relevant documents] may be incomplete or irrelevant. You do not make assumptions
# Customer
You are helping user to find answers to their questions.

user:
{{question}}

To retrieve elements from the generator results, use the following Python code:

python
from promptflow.core import Prompty

# load prompty as a flow
prompty_func = Prompty.load("stream_output.prompty")
# execute the flow as function
question = "What's the steps to get rich?"
result = prompty_func(first_name="John", last_name="Doh", question=question)
# Type of the result is generator
for item in result:
    print(item, end="")

How To Guides Develop A Prompty Use Prompty In Flow (`docs/how-to-guides/develop-a-prompty/use-prompty-in-flow.md`)

Using prompty in flow

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Since Prompty can be called as a function, a user can use prompty in a flow which can be a python function or class.
This allows the user to do more customization logic with prompty.

Consume prompty in code

Example prompty:

text
---
name: Stream Chat
description: Chat with stream enabled.
model:
  api: chat
  configuration:
    type: azure_openai
    azure_deployment: gpt-35-turbo
  parameters:
    temperature: 0.2
    stream: true

inputs:
  first_name:
    type: string
  last_name:
    type: string
  question:
    type: string
  chat_history:
    type: list
sample:
  first_name: John
  last_name: Doe
  question: What is Prompt flow?
  chat_history: [ { "role": "user", "content": "what's the capital of France?" }, { "role": "assistant", "content": "Paris" } ]
---
system:
You are a helpful assistant.
Here is a chat history you had with the user:
{% for item in chat_history %}
{{item.role}}:
{{item.content}}
{% endfor %}

user:
{{question}}

Example python code:

python
from promptflow.tracing import trace
from promptflow.core import AzureOpenAIModelConfiguration, Prompty


class ChatFlow:
    def __init__(self, model_config: AzureOpenAIModelConfiguration):
        self.model_config = model_config

    @trace
    def __call__(
        self, question: str = "What is ChatGPT?", chat_history: list = None
    ) -> str:
        """Flow entry function."""

        chat_history = chat_history or []

        prompty = Prompty.load(
            source="path/to/chat.prompty",
            model={"configuration": self.model_config},
        )

        # output is a generator of string as prompty enabled stream parameter
        output = prompty(question=question, chat_history=chat_history)

        return output


if __name__ == "__main__":
    from promptflow.tracing import start_trace

    start_trace()
    config = AzureOpenAIModelConfiguration(
        connection="open_ai_connection", azure_deployment="gpt-35-turbo"
    )
    flow = ChatFlow(model_config=config)
    result = flow("What's Azure Machine Learning?", [])

    # print result in stream manner
    for r in result:
        print(r, end="")

Run as normal python file

User can run above code as normal python file.

batch
python path/to/entry.py

Test the class as a flow

User can also leverage promptflow to test the class as a flow.

bash
pf flow test --flow file:ChatFlow --init init.json --inputs question="What is ChatGPT?"

With the flow concept, user can further do a rich set of tasks, like:

Check the next section to learn more on flow.


How To Guides Develop A Tool Add A Tool Icon (`docs/how-to-guides/develop-a-tool/add-a-tool-icon.md`)

Adding a Tool Icon

A tool icon serves as a graphical representation of your tool in the user interface (UI). Follow this guidance to add a custom tool icon when developing your own tool package.

Adding a custom tool icon is optional. If you do not provide one, the system uses a default icon.

Prerequisites

  • Please ensure that your Prompt flow for VS Code is updated to version 1.4.2 or later.

  • Create a tool package as described in Create and Use Tool Package.

  • Prepare custom icon image that meets these requirements:

    • Use PNG, JPG or BMP format.
    • 16x16 pixels to prevent distortion when resizing.
    • Avoid complex images with lots of detail or contrast, as they may not resize well.

    See this example as a reference.

  • Install dependencies to generate icon data URI:

    text
    pip install pillow

Add tool icon with _icon_ parameter

Run the command below in your tool project directory to automatically generate your tool YAML, use -i or --icon parameter to add a custom tool icon:

text
python <promptflow github repo>\scripts\tool\generate_package_tool_meta.py -m <tool_module> -o <tool_yaml_path> -i <tool-icon-path>

Here we use an existing tool project as an example.

text
cd D:\proj\github\promptflow\examples\tools\tool-package-quickstart

python D:\proj\github\promptflow\scripts\tool\generate_package_tool_meta.py -m my_tool_package.tools.my_tool_1 -o my_tool_package\yamls\my_tool_1.yaml -i my_tool_package\icons\custom-tool-icon.png

In the auto-generated tool YAML file, the custom tool icon data URI is added in the icon field:

yaml
my_tool_package.tools.my_tool_1.my_tool:
  function: my_tool
  icon: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACR0lEQVR4nKWS3UuTcRTHP79nm9ujM+fccqFGI5viRRpjJgkJ3hiCENVN/QMWdBHUVRdBNwX9ARHd2FVEWFLRjaS9XPmSC/EFTNOWc3Pi48y9PHNzz68L7UXTCvreHM65+PA953uElFLyHzLvHMwsJrnzfJqFeAan3cKV9mr8XseeAOXX5vqjSS53jdF+tIz1nIFAMDCzwpvJ5b87+LSYYHw+gcWkEAwluXnOR2Q1R+9YjJ7BKJG4zoXmqr0ddL3+QnV5EeUOK821LsJammcjEeZiafJScrd3bm8H6zkDd4mVztZKAK49/Mj8is4Z/35GPq9R5VJ5GYztDtB1HT1vovGQSiqVAqDugI3I6jpP3i9x9VQVfu8+1N/OvbWCqqqoBSa6h1fQNA1N0xiYTWJSBCZF8HgwSjQapbRQ2RUg5NYj3O6ZochmYkFL03S4mImIzjFvCf2xS5gtCRYXWvBUvKXjyEVeTN/DXuDgxsnuzSMK4HTAw1Q0hZba4NXEKp0tbpq9VkxCwTAETrsVwxBIBIYhMPI7YqyrtONQzSznJXrO4H5/GJ9LUGg0YFYydJxoYnwpj1s9SEN5KzZz4fYYAW6dr+VsowdFgamlPE/Hs8SzQZYzg0S+zjIc6iOWDDEc6uND+N12B9/VVu+mrd79o38wFCCdTeBSK6hxBii1eahxBlAtRbsDdmoiHGRNj1NZ7GM0NISvzM9oaIhiqwOO/wMgl4FsRpLf2KxGXpLNSLLInzH+CWBIA6RECIGUEiEUpDRACBSh8A3pXfGWdXfMgAAAAABJRU5ErkJggg==
  inputs:
    connection:
      type:
      - CustomConnection
    input_text:
      type:
      - string
  module: my_tool_package.tools.my_tool_1
  name: my_tool
  type: python

Verify the tool icon in VS Code extension

Follow steps to use your tool from VS Code extension. Your tool displays with the custom icon:

FAQ

Can I preview the tool icon image before adding it to a tool?

Yes, you could run below command under the root folder to generate a data URI for your custom tool icon. Make sure the output file has an .html extension.

text
python <path-to-scripts>\tool\convert_image_to_data_url.py --image-path <image_input_path> -o <html_output_path>

For example:

text
python D:\proj\github\promptflow\scripts\tool\convert_image_to_data_url.py --image-path D:\proj\github\promptflow\examples\tools\tool-package-quickstart\my_tool_package\icons\custom-tool-icon.png -o output.html

The content of output.html looks like the following, open it in a web browser to preview the icon.

html
<html>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACR0lEQVR4nKWS3UuTcRTHP79nm9ujM+fccqFGI5viRRpjJgkJ3hiCENVN/QMWdBHUVRdBNwX9ARHd2FVEWFLRjaS9XPmSC/EFTNOWc3Pi48y9PHNzz68L7UXTCvreHM65+PA953uElFLyHzLvHMwsJrnzfJqFeAan3cKV9mr8XseeAOXX5vqjSS53jdF+tIz1nIFAMDCzwpvJ5b87+LSYYHw+gcWkEAwluXnOR2Q1R+9YjJ7BKJG4zoXmqr0ddL3+QnV5EeUOK821LsJammcjEeZiafJScrd3bm8H6zkDd4mVztZKAK49/Mj8is4Z/35GPq9R5VJ5GYztDtB1HT1vovGQSiqVAqDugI3I6jpP3i9x9VQVfu8+1N/OvbWCqqqoBSa6h1fQNA1N0xiYTWJSBCZF8HgwSjQapbRQ2RUg5NYj3O6ZochmYkFL03S4mImIzjFvCf2xS5gtCRYXWvBUvKXjyEVeTN/DXuDgxsnuzSMK4HTAw1Q0hZba4NXEKp0tbpq9VkxCwTAETrsVwxBIBIYhMPI7YqyrtONQzSznJXrO4H5/GJ9LUGg0YFYydJxoYnwpj1s9SEN5KzZz4fYYAW6dr+VsowdFgamlPE/Hs8SzQZYzg0S+zjIc6iOWDDEc6uND+N12B9/VVu+mrd79o38wFCCdTeBSK6hxBii1eahxBlAtRbsDdmoiHGRNj1NZ7GM0NISvzM9oaIhiqwOO/wMgl4FsRpLf2KxGXpLNSLLInzH+CWBIA6RECIGUEiEUpDRACBSh8A3pXfGWdXfMgAAAAABJRU5ErkJggg==" alt="My Image">
</body>
</html>

Can I add a tool icon to an existing tool package?

Yes, you can refer to the preview icon section to generate the data URI and manually add the data URI to the tool's YAML file.

Can I add tool icons for dark and light mode separately?

Yes, you can add the tool icon data URIs manually or run the command below in your tool project directory to automatically generate your tool YAML, use --icon-light to add a custom tool icon for the light mode and use --icon-dark to add a custom tool icon for the dark mode:

text
python <promptflow github repo>\scripts\tool\generate_package_tool_meta.py -m <tool_module> -o <tool_yaml_path> --icon-light <light-tool-icon-path> --icon-dark <dark-tool-icon-path>

Here we use an existing tool project as an example.

text
cd D:\proj\github\promptflow\examples\tools\tool-package-quickstart

python D:\proj\github\promptflow\scripts\tool\generate_package_tool_meta.py -m my_tool_package.tools.my_tool_1 -o my_tool_package\yamls\my_tool_1.yaml --icon-light my_tool_package\icons\custom-tool-icon-light.png --icon-dark my_tool_package\icons\custom-tool-icon-dark.png

In the auto-generated tool YAML file, the light and dark tool icon data URIs are added in the icon field:

text
/* Detailed source-code truncated for AI context efficiency. */

Note: Both light and dark icons are optional. If you set either a light or dark icon, it will be used in its respective mode, and the system default icon will be used in the other mode.


How To Guides Develop A Tool Add Category And Tags For Tool (`docs/how-to-guides/develop-a-tool/add-category-and-tags-for-tool.md`)

Adding Category and Tags for Tool

This document is dedicated to guiding you through the process of categorizing and tagging your tools for optimal organization and efficiency. Categories help you organize your tools into specific folders, making it much easier to find what you need. Tags, on the other hand, work like labels that offer more detailed descriptions. They enable you to quickly search and filter tools based on specific characteristics or functions. By using categories and tags, you'll not only tailor your tool library to your preferences but also save time by effortlessly finding the right tool for any task.

Attribute Type Required Description
category str No Organizes tools into folders by common features.
tags dict No Offers detailed, searchable descriptions of tools through key-value pairs.

Important Notes:

  • Tools without an assigned category will be listed in the root folder.
  • Tools lacking tags will display an empty tags field.

Prerequisites

How to add category and tags for a tool

Run the command below in your tool project directory to automatically generate your tool YAML, use -c or --category to add category, and use --tags to add tags for your tool:

text
python <promptflow github repo>\scripts\tool\generate_package_tool_meta.py -m <tool_module> -o <tool_yaml_path> --category <tool_category> --tags <tool_tags>

Here, we use an existing tool as an example. If you wish to create your own tool, please refer to the create and use tool package guide.

text
cd D:\proj\github\promptflow\examples\tools\tool-package-quickstart

python D:\proj\github\promptflow\scripts\tool\generate_package_tool_meta.py -m my_tool_package.tools.my_tool_1 -o my_tool_package\yamls\my_tool_1.yaml --category "test_tool" --tags "{'tag1':'value1','tag2':'value2'}"

In the auto-generated tool YAML file, the category and tags are shown as below:

yaml
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
  # Category and tags are shown as below.
  category: test_tool
  tags:
    tag1: value1
    tag2: value2

Tool with category and tags experience in VS Code extension

Follow the steps to use your tool via the VS Code extension.

  • Experience in the tool tree

  • Experience in the tool list
    By clicking More in the visual editor, you can view your tools along with their category and tags:

Furthermore, you have the option to search or filter tools based on tags:


How To Guides Develop A Tool Create And Use Tool Package (`docs/how-to-guides/develop-a-tool/create-and-use-tool-package.md`)

Create and Use Tool Package

In this document, we will guide you through the process of developing your own tool package, offering detailed steps and advice on how to utilize your creation.

The custom tool is the prompt flow tool developed by yourself. If you find it useful, you can follow this guidance to make it a tool package. This will enable you to conveniently reuse it, share it with your team, or distribute it to anyone in the world.

After successful installation of the package, your custom "tool" will show up in VSCode extension as below:

Create your own tool package

Your tool package should be a python package. To try it quickly, just use my-tools-package 0.0.1 and skip this section.

Prerequisites

Create a new conda environment using python 3.9 or 3.10. Run below command to install PromptFlow dependencies:

text
pip install promptflow

Install Pytest packages for running tests:

text
pip install pytest pytest-mock

Clone the PromptFlow repository from GitHub using the following command:

text
git clone https://github.com/microsoft/promptflow.git

Create custom tool package

Run below command under the root folder to create your tool project quickly:

text
python <promptflow github repo>\scripts\tool\generate_tool_package_template.py --destination <your-tool-project> --package-name <your-package-name> --tool-name <your-tool-name> --function-name <your-tool-function-name>

For example:

text
python D:\proj\github\promptflow\scripts\tool\generate_tool_package_template.py --destination hello-world-proj --package-name hello-world --tool-name hello_world_tool --function-name get_greeting_message

This auto-generated script will create one tool for you. The parameters destination and package-name are mandatory. The parameters tool-name and function-name are optional. If left unfilled, the tool-name will default to hello_world_tool, and the function-name will default to tool-name.

The command will generate the tool project as follows with one tool hello_world_tool.py in it:

text
hello-world-proj/    
β”‚    
β”œβ”€β”€ hello_world/    
β”‚   β”œβ”€β”€ tools/    
β”‚   β”‚   β”œβ”€β”€ __init__.py    
β”‚   β”‚   β”œβ”€β”€ hello_world_tool.py    
β”‚   β”‚   └── utils.py    
β”‚   β”œβ”€β”€ yamls/    
β”‚   β”‚   └── hello_world_tool.yaml    
β”‚   └── __init__.py    
β”‚    
β”œβ”€β”€ tests/     
β”‚   β”œβ”€β”€ __init__.py    
β”‚   └── test_hello_world_tool.py    
β”‚    
β”œβ”€β”€ MANIFEST.in    
β”‚    
└── setup.py

The points outlined below explain the purpose of each folder/file in the package. If your aim is to develop multiple tools within your package, please make sure to closely examine point 2 and 5.

  1. hello-world-proj: This is the source directory. All of your project's source code should be placed in this directory.

  2. hello-world/tools: This directory contains the individual tools for your project. Your tool package can contain either one tool or many tools. When adding a new tool, you should create another *_tool.py under the tools folder.

  3. hello-world/tools/hello_world_tool.py: Develop your tool within the def function. Use the @tool decorator to identify the function as a tool.

    [!Note] There are two ways to write a tool. The default and recommended way is the function implemented way. You can also use the class implementation way, referring to my_tool_2.py as an example.

  4. hello-world/tools/utils.py: This file implements the tool list method, which collects all the tools defined. It is required to have this tool list method, as it allows the User Interface (UI) to retrieve your tools and display them within the UI.

    [!Note] There's no need to create your own list method if you maintain the existing folder structure. You can simply use the auto-generated list method provided in the utils.py file.

  5. hello_world/yamls/hello_world_tool.yaml: Tool YAMLs defines the metadata of the tool. The tool list method, as outlined in the utils.py, fetches these tool YAMLs.

    [!Note] If you create a new tool, don't forget to also create the corresponding tool YAML. You can run below command under your tool project to auto generate your tool YAML. You may want to specify -n for name and -d for description, which would be displayed as the tool name and tooltip in prompt flow UI.

    text
    python <promptflow github repo>\scripts\tool\generate_package_tool_meta.py -m <tool_module> -o <tool_yaml_path> -n <tool_name> -d <tool_description>

    For example:

    text
    python D:\proj\github\promptflow\scripts\tool\generate_package_tool_meta.py -m hello_world.tools.hello_world_tool -o hello_world\yamls\hello_world_tool.yaml -n "Hello World Tool" -d "This is my hello world tool."

    To populate your tool module, adhere to the pattern .tools.<tool_name>, which represents the folder path to your tool within the package.

  6. tests: This directory contains all your tests, though they are not required for creating your custom tool package. When adding a new tool, you can also create corresponding tests and place them in this directory. Run below command under your tool project:

    text
    pytest tests
  7. MANIFEST.in: This file is used to determine which files to include in the distribution of the project. Tool YAML files should be included in MANIFEST.in so that your tool YAMLs would be packaged and your tools can show in the UI.

    [!Note] There's no need to update this file if you maintain the existing folder structure.

  8. setup.py: This file contains metadata about your project like the name, version, author, and more. Additionally, the entry point is automatically configured for you in the generate_tool_package_template.py script. In Python, configuring the entry point in setup.py helps establish the primary execution point for a package, streamlining its integration with other software.

    The package_tools entry point together with the tool list method are used to retrieve all the tools and display them in the UI.

    python
    entry_points={
          "package_tools": ["<your_tool_name> = <list_module>:<list_method>"],
    },

    [!Note] There's no need to update this file if you maintain the existing folder structure.

Build and share the tool package

Execute the following command in the tool package root directory to build your tool package:

text
python setup.py sdist bdist_wheel

This will generate a tool package <your-package>-0.0.1.tar.gz and corresponding whl file inside the dist folder.

Create an account on PyPI if you don't already have one, and install twine package by running pip install twine.

Upload your package to PyPI by running twine upload dist/*, this will prompt you for your Pypi username and password, and then upload your package on PyPI. Once your package is uploaded to PyPI, others can install it using pip by running pip install your-package-name. Make sure to replace your-package-name with the name of your package as it appears on PyPI.

If you only want to put it on Test PyPI, upload your package by running twine upload --repository-url https://test.pypi.org/legacy/ dist/*. Once your package is uploaded to Test PyPI, others can install it using pip by running pip install --index-url https://test.pypi.org/simple/ your-package-name.

Use your tool from VSCode Extension

  • Step1: Install Prompt flow for VS Code extension.

  • Step2: Go to terminal and install your tool package in conda environment of the extension. Assume your conda env name is prompt-flow.

    text
    (local_test) PS D:\projects\promptflow\tool-package-quickstart> conda activate prompt-flow
    (prompt-flow) PS D:\projects\promptflow\tool-package-quickstart> pip install .\dist\my_tools_package-0.0.1-py3-none-any.whl
  • Step3: Go to the extension and open one flow folder. Click 'flow.dag.yaml' and preview the flow. Next, click + button and you will see your tools. You may need to reload the windows to clean previous cache if you don't see your tool in the list.

FAQs

Why is my custom tool not showing up in the UI?

Confirm that the tool YAML files are included in your custom tool package. You can add the YAML files to MANIFEST.in and include the package data in setup.py.
Alternatively, you can test your tool package using the script below to ensure that you've packaged your tool YAML files and configured the package tool entry point correctly.

  1. Make sure to install the tool package in your conda environment before executing this script.
  2. Create a python file anywhere and copy the content below into it.
    python
    import importlib
    import importlib.metadata
    
    def test():
        """List all package tools information using the `package-tools` entry point.
    
        This function iterates through all entry points registered under the group "package_tools."
        For each tool, it imports the associated module to ensure its validity and then prints
        information about the tool.
    
        Note:
        - Make sure your package is correctly packed to appear in the list.
        - The module is imported to validate its presence and correctness.
    
        Example of tool information printed:
        ----identifier
        {'module': 'module_name', 'package': 'package_name', 'package_version': 'package_version', ...}
        """
        entry_points = importlib.metadata.entry_points()
        if hasattr(entry_points, "select"):
            entry_points = entry_points.select(group=PACKAGE_TOOLS_ENTRY)
        else:
            entry_points = entry_points.get(PACKAGE_TOOLS_ENTRY, [])
        for entry_point in entry_points:
            list_tool_func = entry_point.load()
            package_tools = list_tool_func()
    
            for identifier, tool in package_tools.items():
                importlib.import_module(tool["module"])  # Import the module to ensure its validity
                print(f"----{identifier}\n{tool}")
    
    if __name__ == "__main__":
        test()
  3. Run this script in your conda environment. This will return the metadata of all tools installed in your local environment, and you should verify that your tools are listed.

Why am I unable to upload package to PyPI?

  • Make sure that the entered username and password of your PyPI account are accurate.
  • If you encounter a 403 Forbidden Error, it's likely due to a naming conflict with an existing package. You will need to choose a different name. Package names must be unique on PyPI to avoid confusion and conflicts among users. Before creating a new package, it's recommended to search PyPI (https://pypi.org/) to verify that your chosen name is not already taken. If the name you want is unavailable, consider selecting an alternative name or a variation that clearly differentiates your package from the existing one.

Advanced features


How To Guides Develop A Tool Create Cascading Tool Inputs (`docs/how-to-guides/develop-a-tool/create-cascading-tool-inputs.md`)

Creating Cascading Tool Inputs

Cascading input settings are useful when the value of one input field determines which subsequent inputs are shown. This makes the input process more streamlined, user-friendly, and error-free. This guide will walk through how to create cascading inputs for your tools.

Prerequisites

Please make sure you have the latest version of Prompt flow for VS Code installed (v1.2.0+).

Create a tool with cascading inputs

We'll build out an example tool to show how cascading inputs work. The student_id and teacher_id inputs will be controlled by the value selected for the user_type input. Here's how to configure this in the tool code and YAML.

  1. Develop the tool function, following the cascading inputs example. Key points:
    • Use the @tool decorator to mark the function as a tool.
    • Define UserType as an Enum class, as it accepts only a specific set of fixed values in this example.
    • Conditionally use inputs in the tool logic based on user_type.
python
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.")
  1. Generate a starting YAML for your tool per the tool package guide, then update it to enable cascading:

    Add enabled_by and enabled_by_value to control visibility of dependent inputs. See the example YAML for reference.

    • The enabled_by attribute specifies the input field, which must be an enum type, that controls the visibility of the dependent input field.

    • The enabled_by_value attribute defines the accepted enum values from the enabled_by field that will make this dependent input field visible.

    Note: enabled_by_value takes a list, allowing multiple values to enable an input.

yaml
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
      # This input is enabled by the input "user_type".
      enabled_by: user_type
      # This input is enabled when "user_type" is "student".
      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

Use the tool in VS Code

Once you package and share your tool, you can use it in VS Code per the tool package guide. We have a demo flow you can try.

Before selecting a user_type, the student_id and teacher_id inputs are hidden. Once you pick the user_type, the corresponding input appears.

FAQs

How do I create multi-layer cascading inputs?

If you are dealing with multiple levels of cascading inputs, you can effectively manage the dependencies between them by using the enabled_by and enabled_by_value attributes. For example:

yaml
my_tool_package.tools.tool_with_multi_layer_cascading_inputs.my_tool:
  function: my_tool
  inputs:
    event_type:
      type:
      - string
      enum:
        - corporate
        - private
    corporate_theme:
      type:
      - string
      # This input is enabled by the input "event_type".
      enabled_by: event_type
      # This input is enabled when "event_type" is "corporate".
      enabled_by_value: [corporate]
      enum:
        - seminar
        - team_building
    seminar_location:
      type:
      - string
      # This input is enabled by the input "corporate_theme".
      enabled_by: corporate_theme
      # This input is enabled when "corporate_theme" is "seminar".
      enabled_by_value: [seminar]
    private_theme:
      type:
        - string
      # This input is enabled by the input "event_type".
      enabled_by: event_type
      # This input is enabled when "event_type" is "private".
      enabled_by_value: [private]
  module: my_tool_package.tools.tool_with_multi_layer_cascading_inputs
  name: My Tool with Multi-Layer Cascading Inputs
  description: This is my tool with multi-layer cascading inputs
  type: python

Inputs will be enabled in a cascading way based on selections.


How To Guides Develop A Tool Create Dynamic List Tool Input (`docs/how-to-guides/develop-a-tool/create-dynamic-list-tool-input.md`)

Creating a Dynamic List Tool Input

Tool input options can be generated on the fly using a dynamic list. Instead of having predefined static options, the tool author defines a request function that queries backends like APIs to retrieve real-time options. This enables flexible integration with various data sources to populate dynamic options. For instance, the function could call a storage API to list current files. Rather than a hardcoded list, the user sees up-to-date options when running the tool.

Prerequisites

  • Please make sure you have the latest version of Prompt flow for VS Code installed (v1.3.1+).
  • Please install promptflow package and ensure that its version is 1.0.0 or later.
    text
    pip install promptflow>=1.0.0

Create a tool input with dynamic listing

Create a list function

To enable dynamic listing, the tool author defines a request function with the following structure:

  • Type: Regular Python function, can be in tool file or separate file
  • Input: Accepts parameters needed to fetch options
  • Output: Returns a list of option objects as List[Dict[str, Union[str, int, float, list, Dict]]]:
    • Required key:
      • value: Internal option value passed to tool function
    • Optional keys:
      • display_value: Display text shown in dropdown (defaults to value)
      • hyperlink: URL to open when option clicked
      • description: Tooltip text on hover

This function can make backend calls to retrieve the latest options, returning them in a standardized dictionary structure for the dynamic list. The required and optional keys enable configuring how each option appears and behaves in the tool input dropdown. See my_list_func as an example.

python
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

Configure a tool input with the list function

In inputs section of tool YAML, add following properties to the input that you want to make dynamic:

  • dynamic_list:
    • func_path: Path to the list function (module_name.function_name).
    • func_kwargs: Parameters to pass to the function, can reference other input values.
  • allow_manual_entry: Allow user to enter input value manually. Default to false.
  • is_multi_select: Allow user to select multiple values. Default to false.

See tool_with_dynamic_list_input.yaml as an example.

yaml
my_tool_package.tools.tool_with_dynamic_list_input.my_tool:
  function: my_tool
  inputs:
    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
    # used to filter 
    input_prefix:
      type:
      - string
  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

Use the tool in VS Code

Once you package and share your tool, you can use it in VS Code per the tool package guide. You could try my-tools-package for a quick test.

sh
pip install my-tools-package>=0.0.8

Note: If your dynamic list function call Azure APIs, you need to login to Azure and set default workspace. Otherwise, the tool input will be empty and you can't select anything. See FAQs for more details.

FAQs

I'm a tool author, and want to dynamically list Azure resources in my tool input. What should I pay attention to?

  1. Clarify azure workspace triple "subscription_id", "resource_group_name", "workspace_name" in the list function signature. System helps append workspace triple to function input parameters if they are in function signature. See list_endpoint_names as an example.
text
/* Detailed source-code truncated for AI context efficiency. */
  1. Note in your tool doc that if your tool user want to use the tool at local, they should login to azure and set ws triple as default. Or the tool input will be empty and user can't select anything.
sh
az login
az account set --subscription <subscription_id>
az configure --defaults group=<resource_group_name> workspace=<workspace_name>

Install azure dependencies.

sh
pip install azure-ai-ml
sh
pip install my-tools-package[azure]>=0.0.8

I'm a tool user, and cannot see any options in dynamic list tool input. What should I do?

If you are unable to see any options in a dynamic list tool input, you may see an error message below the input field stating:

"Unable to retrieve result due to XXX. Please contact the tool author/support team for troubleshooting assistance."

If this occurs, follow these troubleshooting steps:

  • Note the exact error message shown. This provides details on why the dynamic list failed to populate.
  • Check the tool documentation for any prerequisites or special instructions. For example, if the dynamic list function requires Azure credentials, ensure you have installed azure dependencies, logged in and set the default workspace.
    sh
    pip install azure-ai-ml
    sh
    az login
    az account set --subscription <subscription_id>
    az configure --defaults group=<resource_group_name> workspace=<workspace_name>
  • Contact the tool author/support team and report the issue. Provide the error message so they can investigate the root cause.

How To Guides Develop A Tool Create Your Own Custom Strong Type Connection (`docs/how-to-guides/develop-a-tool/create-your-own-custom-strong-type-connection.md`)

Create and Use Your Own Custom Strong Type Connection

Connections provide a secure method for managing credentials for external APIs and data sources in prompt flow. This guide explains how to create and use a custom strong type connection.

What is a Custom Strong Type Connection?

A custom strong type connection in prompt flow allows you to define a custom connection class with strongly typed keys. This provides the following benefits:

  • Enhanced user experience - no need to manually enter connection keys.
  • Rich intellisense experience - defining key types enables real-time suggestions and auto-completion of available keys as you work in VS Code.
  • Central location to view available keys and data types.

For other connections types, please refer to Connections.

Prerequisites

  • Please ensure that your Prompt flow for VS Code is updated to at least version 1.2.1.
  • Please install promptflow package and ensure that its version is 0.1.0b8 or later.
    text
    pip install promptflow>=0.1.0b8

Create a custom strong type connection

Follow these steps to create a custom strong type connection:

  1. Define a Python class inheriting from CustomStrongTypeConnection.

[!Note] Please avoid using the CustomStrongTypeConnection class directly.

  1. Use the Secret type to indicate secure keys. This enhances security by scrubbing secret keys.

  2. Document with docstrings explaining each key.

For example:

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: Secret
    :param api_base: The api base.
    :type api_base: String
    """
    api_key: Secret
    api_base: str = "This is a fake api base."

See this example for a complete implementation.

Use the connection in a flow

Once you create a custom strong type connection, here are two ways to use it in your flows:

With Package Tools:

  1. Refer to the Create and Use Tool Package to build and install your tool package containing the connection.

  2. Develop a flow with custom tools. Please take this folder as an example.

  3. Create a custom strong type connection using one of the following methods:

    • If the connection type hasn't been created previously, click the 'Add connection' button to create the connection.

    • Click the 'Create connection' plus sign in the CONNECTIONS section.

    • Click 'Create connection' plus sign in the Custom category.

  4. Fill in the values starting with to-replace-with in the connection template.

  5. Run the flow with the created custom strong type connection.

With Script Tools:

  1. Develop a flow with python script tools. Please take this folder as an example.

  2. Create a CustomConnection. Fill in the keys and values in the connection template.

  3. Run the flow with the created custom connection.

Local to cloud

When creating the necessary connections in Azure AI, you will need to create a CustomConnection. In the node interface of your flow, this connection will be displayed as the CustomConnection type.

Please refer to Run prompt flow in Azure AI for more details.

Here is an example command:

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

FAQs

I followed the steps to create a custom strong type connection, but it's not showing up. What could be the issue?

Once the new tool package is installed in your local environment, a window reload is necessary. This action ensures that the new tools and custom strong type connections become visible and accessible.


How To Guides Develop A Tool Customize An Llm Tool (`docs/how-to-guides/develop-a-tool/customize_an_llm_tool.md`)

Customizing an LLM Tool

In this document, we will guide you through the process of customizing an LLM tool, allowing users to seamlessly connect to a large language model with prompt tuning experience using a PromptTemplate.

Prerequisites

How to customize an LLM tool

Here we use an existing tool package as an example. If you want to create your own tool, please refer to create and use tool package.

  1. Develop the tool code as in this example.
  • Add a CustomConnection input to the tool, which is used to authenticate and establish a connection to the large language model.

  • Add a PromptTemplate input to the tool, which serves as an argument to be passed into the large language model.

    python
    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
  1. Generate the custom LLM tool YAML.
    Run the command below in your tool project directory to automatically generate your tool YAML, use -t "custom_llm" or --tool-type "custom_llm" to indicate this is a custom LLM tool:

    text
    python <promptflow github repo>\scripts\tool\generate_package_tool_meta.py -m <tool_module> -o <tool_yaml_path> -t "custom_llm"

    Here we use an existing tool as an example.

    text
    cd D:\proj\github\promptflow\examples\tools\tool-package-quickstart
    
    python D:\proj\github\promptflow\scripts\tool\generate_package_tool_meta.py -m my_tool_package.tools.tool_with_custom_llm_type -o my_tool_package\yamls\tool_with_custom_llm_type.yaml -n "My Custom LLM Tool" -d "This is a tool to demonstrate how to customize an LLM tool with a PromptTemplate." -t "custom_llm"

    This command will generate a YAML file as follows:

    yaml
    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.
    # The type is custom_llm.
    type: custom_llm
    module: my_tool_package.tools.tool_with_custom_llm_type
    function: my_tool
    inputs:
      connection:
        type:
          - CustomConnection
      api:
        type:
          - string
      deployment_name:
        type:
          - string
      temperature:
        type:
          - double

Use the tool in VS Code

Follow the steps to build and install your tool package and use your tool from VS Code extension.

Here we use an existing flow to demonstrate the experience, open this flow in VS Code extension.

  • There is a node named "my_custom_llm_tool" with a prompt template file. You can either use an existing file or create a new one as the prompt template file.

FAQs

Can I customize text box size for my tool inputs?

Yes, you can add ui_hints.text_box_size field for your tool inputs. There are 4 sizes available which range from extra small to large as xs, sm, md, lg. The table below provides detailed information about these sizes:

Value Description UI display size
xs extra small 40px
sm small 80px
md medium 130px
lg large 180px

You can choose to use different values for your tool inputs based on their expected value length. Take the following yaml as example:

yaml
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

When you use the tool in this example flow, you could see the sizes of the input text boxes are displayed as the set values.


How To Guides Develop A Tool Use File Path As Tool Input (`docs/how-to-guides/develop-a-tool/use-file-path-as-tool-input.md`)

Using File Path as Tool Input

Users sometimes need to reference local files within a tool to implement specific logic. To simplify this, we've introduced the FilePath input type. This input type enables users to either select an existing file or create a new one, then pass it to a tool, allowing the tool to access the file's content.

In this guide, we will provide a detailed walkthrough on how to use FilePath as a tool input. We will also demonstrate the user experience when utilizing this type of tool within a flow.

Prerequisites

  • Please install promptflow package and ensure that its version is 0.1.0b8 or later.
    text
    pip install promptflow>=0.1.0b8
  • Please ensure that your Prompt flow for VS Code is updated to version 1.1.0 or later.

Using File Path as Package Tool Input

How to create a package tool with file path input

Here we use an existing tool package as an example. If you want to create your own tool, please refer to create and use tool package.

  1. Add a FilePath input for your tool, like in this example.

    python
    import importlib
    from pathlib import Path
    from promptflow.core import tool
    # 1. import the FilePath type
    from promptflow.contracts.types import FilePath
    
    # 2. add a FilePath input for your tool method
    @tool
    def my_tool(input_file: FilePath, input_text: str) -> str:
        # 3. 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)
  2. FilePath input format in a tool YAML, like in this example.

    yaml
    my_tool_package.tools.tool_with_file_path_input.my_tool:
       function: my_tool
         inputs:
           # yaml format for FilePath input
           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

    [!Note] tool yaml file can be generated using a python script. For further details, please refer to create custom tool package.

Use tool with a file path input in VS Code extension

Follow steps to build and install your tool package and use your tool from VS Code extension.

Here we use an existing flow to demonstrate the experience, open this flow in VS Code extension:

  • There is a node named "Tool_with_FilePath_Input" with a file_path type input called input_file.
  • Click the picker icon to open the UI for selecting an existing file or creating a new file to use as input.

Using File Path as Script Tool Input

We can also utilize the FilePath input type directly in a script tool, eliminating the need to create a package tool.

  1. Initiate an empty flow in the VS Code extension and add a python node titled 'python_node_with_filepath' into it in the Visual Editor page.

  2. Select the link python_node_with_filepath.py in the node to modify the python method to include a FilePath input as shown below, and save the code change.

    python
    import importlib
    from pathlib import Path
    from promptflow.core import tool
    # 1. import the FilePath type
    from promptflow.contracts.types import FilePath
    
    # 2. add a FilePath input for your tool method
    @tool
    def my_tool(input_file: FilePath, input_text: str) -> str:
        # 3. 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)
  3. Return to the flow Visual Editor page, click the picker icon to launch the UI for selecting an existing file or creating a new file to use as input, here we select this file as an example.

FAQ

What are some practical use cases for this feature?

The FilePath input enables several useful workflows:

  1. Dynamically load modules - As shown in the demo, you can load a Python module from a specific script file selected by the user. This allows flexible custom logic.
  2. Load arbitrary data files - The tool can load data from files like .csv, .txt, .json, etc. This provides an easy way to inject external data into a tool.

So in summary, FilePath input gives tools flexible access to external files provided by users at runtime. This unlocks many useful scenarios like the ones above.


How To Guides Installation Standalone (`docs/how-to-guides/installation/standalone.md`)

Standalone CLI

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

A standalone installation of prompt flow bypasses the need for a Python virtual environment and allows users to
utilize the prompt flow CLI directly in their command terminal. Opt for this option when seeking a swift setup without
concerns about dependencies or virtual environments, and when preferring the straightforward efficiency of the command line interface.

Install

::::{tab-set}

:::{tab-item} Windows
:sync: Windows

You can use winget, Microsoft's Package manager for Windows, to install and manage updates for prompt flow CLI in Windows OS.

Note: winget is available by default in Windows 11 and modern versions of Windows 10. However, it may not be installed
in older versions of Windows. See the winget documentation for installation instructions.

Open a command-line terminal, you can use either PowerShell or Command Prompt (cmd). Run the command below:

powershell
winget install -e --id Microsoft.Promptflow

The -e option is to ensure the official prompt flow package is installed. This command installs the latest version
by default. To specify a version, add a -v <version> with your desired version to the command.
:::

::::

Verify installation

To verify the installation, run the following command to check the version of prompt flow installed.

shell
pf --version

Uninstall

  • If you install prompt flow CLI using winget, you can uninstall it by running the following command in your terminal:
    powershell
    winget uninstall Microsoft.Promptflow

How To Guides Run And Evaluate A Flow Manage Runs (`docs/how-to-guides/run-and-evaluate-a-flow/manage-runs.md`)

Manage runs

This documentation will walk you through how to manage your runs with CLI, SDK and VS Code Extension.

In general:

  • For CLI, you can run pf/pfazure run --help in terminal to see the help messages.
  • For SDK, you can refer to Promptflow Python Library Reference and check PFClient.runs for more run operations.

Let's take a look at the following topics:

Create a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI
To create a run against bulk inputs, you can write the following YAML file.

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Run.schema.json
flow: ../web_classification
data: ../webClassification1.jsonl
column_mapping:
   url: "${data.url}"
variant: ${summarize_text_content.variant_0}

To create a run against existing run, you can write the following YAML file.

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Run.schema.json
flow: ../classification_accuracy_evaluation
data: ../webClassification1.jsonl
column_mapping:
   groundtruth: "${data.answer}"
   prediction: "${run.outputs.category}"
run: <existing-flow-run-name>

Reference here for detailed information for column mapping.
You can find additional information about flow yaml schema in Run YAML Schema.

After preparing the yaml file, use the CLI command below to create them:

bash
# create the flow run
pf run create -f <path-to-flow-run>

# create the flow run and stream output
pf run create -f <path-to-flow-run> --stream

The expected result is as follows if the run is created successfully.

:::

:::{tab-item} SDK
:sync: SDK
Using SDK, create Run object and submit it with PFClient. The following code snippet shows how to import the required class and create the run:

python
from promptflow.client import PFClient
from promptflow.entities import Run

# Get a pf client to manage runs
pf = PFClient()

# Initialize an Run object
run = Run(
    flow="<path-to-local-flow>",
    # run flow against local data or existing run, only one of data & run can be specified.
    data="<path-to-data>",
    run="<existing-run-name>",
    column_mapping={"url": "${data.url}"},
    variant="${summarize_text_content.variant_0}"
)

# Create the run
result = pf.runs.create_or_update(run)
print(result)

:::

:::{tab-item} VS Code Extension
:sync: VS Code Extension

You can click on the actions on the top of the default yaml editor or the visual editor for the flow.dag.yaml files to trigger flow batch runs.

:::
::::

Get a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Get a run in CLI with JSON format.

bash
pf run show --name <run-name>

:::

:::{tab-item} SDK
:sync: SDK
Show run with PFClient

python
from promptflow.client import PFClient
# Get a pf client to manage runs
pf = PFClient()
# Get and print the run
run = pf.runs.get(name="<run-name>")
print(run)

:::

:::{tab-item} VS Code Extension
:sync: VSC

:::
::::

Show run details

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Get run details with TABLE format.

bash
pf run show-details --name <run-name>

:::

:::{tab-item} SDK
:sync: SDK
Show run details with PFClient

python
from promptflow.client import PFClient
from tabulate import tabulate

# Get a pf client to manage runs
pf = PFClient()
# Get and print the run-details
run_details = pf.runs.get_details(name="<run-name>")
print(tabulate(details.head(max_results), headers="keys", tablefmt="grid"))

:::

:::{tab-item} VS Code Extension
:sync: VSC

:::
::::

Show run metrics

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Get run metrics with JSON format.

bash
pf run show-metrics --name <run-name>

:::

:::{tab-item} SDK
:sync: SDK
Show run metrics with PFClient

python
from promptflow.client import PFClient
import json

# Get a pf client to manage runs
pf = PFClient()
# Get and print the run-metrics
run_details = pf.runs.get_metrics(name="<run-name>")
print(json.dumps(metrics, indent=4))

:::

::::

Visualize a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Visualize run in browser.

bash
pf run visualize --names <run-name>

A browser will open and display run outputs.

:::

:::{tab-item} SDK
:sync: SDK
Visualize run with PFClient

python
from promptflow.client import PFClient

# Get a pf client to manage runs
pf = PFClient()
# Visualize the run
client.runs.visualize(runs="<run-name>")

:::

:::{tab-item} VS Code Extension
:sync: VSC

On the VS Code primary sidebar > the prompt flow pane, there is a run list. It will list all the runs on your machine. Select one or more items and click the "visualize" button on the top-right to visualize the local runs.

:::
::::

List runs

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

List runs with JSON format.

bash
pf run list

:::

:::{tab-item} SDK
:sync: SDK
List with PFClient

python
from promptflow.client import PFClient

# Get a pf client to manage runs
pf = PFClient()
# list runs
runs = pf.runs.list()
print(runs)

:::

:::{tab-item} VS Code Extension
:sync: VSC

On the VS Code primary sidebar > the prompt flow pane, there is a run list. It will list all the runs on your machine. Hover on it to view more details.

:::
::::

Update a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Get run metrics with JSON format.

bash
pf run update --name <run-name> --set display_name=new_display_name

:::

:::{tab-item} SDK
:sync: SDK
Update run with PFClient

python
from promptflow.client import PFClient

# Get a pf client to manage runs
pf = PFClient()
# Get and print the run-metrics
run = pf.runs.update(name="<run-name>", display_name="new_display_name")
print(run)

:::
::::

Archive a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Archive the run so it won't show in run list results.

bash
pf run archive --name <run-name>

:::

:::{tab-item} SDK
:sync: SDK
Archive with PFClient

python
from promptflow.client import PFClient

# Get a pf client to manage runs
pf = PFClient()
# archive a run
client.runs.archive(name="<run-name>")

:::

:::{tab-item} VS Code Extension
:sync: VSC

:::
::::

Restore a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Restore an archived run so it can show in run list results.

bash
pf run restore --name <run-name>

:::

:::{tab-item} SDK
:sync: SDK
Restore with PFClient

python
from promptflow.client import PFClient

# Get a pf client to manage runs
pf = PFClient()
# restore a run
client.runs.restore(name="<run-name>")

:::
::::

Delete a run

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

Caution: pf run delete is irreversible. This operation will delete the run permanently from your local disk. Both run entity and output data will be deleted.

Delete will fail if the run name is not valid.

bash
pf run delete --name <run-name>

:::

:::{tab-item} SDK
:sync: SDK
Delete with PFClient

python
from promptflow.client import PFClient

# Get a pf client to manage runs
pf = PFClient()
# delete a run
client.runs.delete(name="run-name")

:::
::::


How To Guides Run And Evaluate A Flow Use Column Mapping (`docs/how-to-guides/run-and-evaluate-a-flow/use-column-mapping.md`)

Use column mapping

In this document, we will introduce how to map inputs with column mapping when running a flow.

Column mapping introduction

Column mapping is a mapping from flow input name to specified values.
If specified, the flow will be executed with provided value for specified inputs.
The following types of values in column mapping are supported:

  • ${data.<column_name>} to reference from your test dataset.
  • ${run.inputs.} to reference from referenced run's input. Note: this only supported when --run is provided for pf run.
  • ${run.outputs.<output_name>} to reference from referenced run's output. Note: this only supported when --run is provided for pf run.
  • STATIC_VALUE to create static value for all lines for specified column.

Flow inputs override priority

Flow input values are overridden according to the following priority:

"specified in column mapping" > "default value" > "same name column in provided data".

For example, if we have a flow with following inputs:

yaml
inputs:
  input1:
    type: string
    default: "default_val1"
  input2:
    type: string
    default: "default_val2"
  input3:
    type: string
  input4:
    type: string
...

And the flow will return each inputs in outputs.

With the following data

json
{"input3": "val3_in_data", "input4": "val4_in_data"}

And use the following YAML to run

yaml
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Run.schema.json
flow: path/to/flow
# my_flow has default value val2 for key2
data: path/to/data
# my_data has column key3 with value val3
column_mapping:
    input1: "val1_in_column_mapping"
    input3: ${data.input3}

Since the flow will return each inputs in output, we can get the actual inputs from outputs.output field in run details:

  • Input "input1" has value "val1_in_column_mapping" since it's specified as constance in column_mapping.
  • Input "input2" has value "default_val2" since it used default value in flow dag.
  • Input "input3" has value "val3_in_data" since it's specified as data reference in column_mapping.
  • Input "input4" has value "val4_in_data" since it has same name column in provided data.

How To Guides Tracing Manage (`docs/how-to-guides/tracing/manage.md`)

Manage traces

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Prompt flow provides several trace toolkits in promptflow-devkit. This page will introduce how to delete traces in local storage with CLI/SDK.

Local trace management

Delete

Prompt flow provides capability to delete traces in local storage, user can delete traces by collection (a bucket of traces, can be specified with start_trace), time range or prompt flow run with both CLI and SDK:

::::{tab-set}
:::{tab-item} CLI
:sync: CLI

bash
pf trace delete --collection <collection-name>  # delete specific collection
pf trace delete --collection <collection-name> --started-before '2024-03-01T16:00:00.123456'  # delete traces started before the time in specific collection
pf trace delete --run <run-name>  # delete traces originated from specific prompt flow run

:::

:::{tab-item} SDK
:sync: SDK

python
from promptflow.client import PFClient

pf = PFClient()
pf.traces.delete(collection="<collection-name>")  # delete specific collection
pf.traces.delete(collection="<collection-name>", started_before="2024-03-01T16:00:00.123456")  # delete traces started before the time in specific collection
pf.traces.delete(run="<run-name>")  # delete traces originated from specific prompt flow run

:::

::::


How To Guides Tracing Trace Ui (`docs/how-to-guides/tracing/trace-ui.md`)

Visualize traces

:::{admonition} Experimental feature
This is an experimental feature, and may change at any time. Learn more.
:::

Prompt flow provides several trace toolkits in promptflow-devkit. This page will introduce trace UI, where user can better capture and visualize the internal execution details for flows. With trace UI, user can track and visualize flow execution, which provides critical insights for developer to understand the internal details of execution.

Overview

With promptflow-devkit installed, running python script with start_trace will produce below example output:

text
Prompt flow service has started...
You can view the traces from local: http://127.0.0.1:<port>/v1.0/ui/traces/?#collection=basic

Click the url, user will see a trace list that corresponding to each LLM calls:

Click on one line record, the LLM detail will be displayed with chat window experience, together with other LLM call params:

When combine trace and flow, trace UI provides a more comprehensive view of the flow execution, user can easily track the flow execution details, and debug the flow execution issues.

Flow test

If your application is created with DAG flow, all flow test and batch run will be automatically enable trace function. Take the chat_with_pdf as example.

Run pf flow test --flow ., each flow test will generate single line in the trace UI:

Click a record, the trace details will be visualized as tree view.

Evaluate against batch data

Keep using chat_with_pdf as example, to trigger a batch run, you can use below command under the folder (you can learn more from Run and evaluate a flow to understand what does below command do):

shell
pf run create --flow . --data "./data/bert-paper-qna.jsonl" --column-mapping chat_history='${data.chat_history}' pdf_url='${data.pdf_url}' question='${data.question}'

Then you will get a run related trace URL, e.g. http://127.0.0.1:/v1.0/ui/traces?run=chat_with_pdf_20240226_181222_219335

Trace UI supports simple Python expression for search experience, which is demonstrated in below GIF:

Currently it supports:

  • Operators:
    • bool: and and or
    • compare: ==, !=, >, >=, < and <=
  • Searchable fields:
    • metadata: name, kind and status
    • time: start_time
    • token count: cumulative_token_count.total, cumulative_token_count.prompt and cumulative_token_count.completion

You can also find the hints by clicking the button right to the search edit box:


Integrations Tools Azure Ai Language Tool (`docs/integrations/tools/azure-ai-language-tool.md`)

Azure AI Language

Azure AI Language enables users with task-oriented and optimized pre-trained or custom language models to effectively understand and analyze documents and conversations. This Prompt flow tool is a wrapper for various Azure AI Language APIs. The current list of supported capabilities is as follows:

Name Description
Abstractive Summarization Generate abstractive summaries from documents.
Extractive Summarization Extract summaries from documents.
Conversation Summarization Summarize conversations.
Entity Recognition Recognize and categorize entities in documents.
Key Phrase Extraction Extract key phrases from documents.
Language Detection Detect the language of documents.
PII Entity Recognition Recognize and redact PII entities in documents.
Conversational PII Recognize and redact PII entities in conversations.
Sentiment Analysis Analyze the sentiment of documents.
Conversational Language Understanding Predict intents and entities from user's utterances.
Translator Translate documents.

Requirements

PyPI package: promptflow-azure-ai-language.

  • For AzureML users:
    follow this wiki, starting from Prepare compute session.
  • For local users:
    text
    pip install promptflow-azure-ai-language
    You may also want to install the Prompt flow for VS Code extension.

Prerequisites

The tool calls APIs from Azure AI Language. To use it, you must create a connection to an Azure AI Language resource. Create a Language Resource first, if necessary.

  • In Prompt flow, add a new CustomConnection.
    • Under the secrets field, specify the resource's API key: api_key: <Azure AI Language Resource api key>
    • Under the configs field, specify the resource's endpoint: endpoint: <Azure AI Language Resource endpoint>

To use the Translator tool, you must set up an additional connection to an Azure AI Translator resource. Create a Translator resource first, if necessary.

  • In Prompt flow, add a new CustomConnection.
    • Under the secrets field, specify the resource's API key: api_key: <Azure AI Translator Resource api key>
    • Under the configs field, specify the resource's endpoint: endpoint: <Azure AI Translator Resource endpoint>
    • If your Translator Resource is regional and non-global, specify its region under configs as well: region: <Azure AI Translator Resource region>

Inputs

When a tool parameter is of type Document, it requires a dict object of this specification.

Example:

text
my_document = {
    "id": "1",
    "text": "This is some document text!",
    "language": "en"
}

When a tool parameter is of type Conversation, it requires a dict object.

Example:

text
my_conversation = {
    "id": "meeting_1",
    "language": "en",
    "modality": "text",
    "domain": "generic",
    "conversationItems": [
        {
            "participantId": "person1",
            "role": "generic",
            "id": "1",
            "text": "Hello!"
        },
        {
            "participantId": "person2",
            "role": "generic",
            "id": "2",
            "text": "How are you?"
        }
    ]
}

All skills have the following (optional) inputs:

Name Type Description Required
max_retries int The maximum number of HTTP request retries. Default value is 5. No
max_wait int The maximum wait time (in seconds) in-between HTTP requests. Default value is 60. No
parse_response bool Should the full API JSON output be parsed to extract the single task result. Default value is False. No

HTTP request logic utilizes exponential backoff.
See skill specific inputs below:


Abstractive Summarization Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
document Document The input document. Yes
query string The query used to structure summarization. Yes
summary_length string (enum) The desired summary length. Enum values are short, medium, and long. No

Extractive Summarization Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
document Document The input document. Yes
query string The query used to structure summarization. Yes
sentence_count int The desired number of output summary sentences. Default value is 3. No
sort_by string (enum) The sorting criteria for extractive summarization results. Enum values are Offset to sort results in order of appearance in the text and Rank to sort results in order of importance (i.e. rank score) according to model. Default value is Offset. No

Conversation Summarization Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
conversation Conversation The input conversation. Yes
summary_aspect string (enum) The desired summary "aspect" to obtain. Enum values are chapterTitle to obtain the chapter title of any conversation, issue to obtain the summary of issues in transcripts of web chats and service calls between customer-service agents and customers, narrative to obtain the generic summary of any conversation, resolution to obtain the summary of resolutions in transcripts of web chats and service calls between customer-service agents and customers, recap to obtain a general summary, and follow-up tasks to obtain a summary of follow-up or action items. Yes

Entity Recognition Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
document Document The input document. Yes

Key Phrase Extraction Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
document Document The input document. Yes

Language Detection Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
text string The input text. Yes

PII Entity Recognition Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
document Document The input document. Yes
domain string (enum) The PII domain used for PII Entity Recognition. Enum values are none for no domain, or phi to indicate that entities in the Personal Health domain should be redacted. Default value is none. No
pii_categories list[string] Describes the PII categories to return. No

Conversational PII Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
conversation Conversation The input conversation. Yes
pii_categories list[string] Describes the PII categories to return for detection. Default value is ['Default']. No
redact_audio_timing bool Should audio stream offset and duration for any detected entities be redacted. Default value is False. No
redaction source string (enum) For transcript conversations, this parameter provides information regarding which content type should be used for entity detection. The details of the entities detected - such as the offset, length, and the text itself - will correspond to the text type selected here. Enum values are lexical, itn, maskedItn, and text. Default value is lexical. No
exclude_pii_categories list[string] Describes the PII categories to exclude for detection. Default value is []. No

Sentiment Analysis Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
document Document The input document. Yes
opinion_mining bool Should opinion mining be enabled. Default value is False. No

Conversational Language Understanding Name Type Description Required
connection CustomConnection The created connection to an Azure AI Language resource. Yes
language string The ISO 639-1 code for the language of the input. Yes
utterances string A single user utterance or a json array of user utterances. Yes
project_name string The Conversational Language Understanding project to be called. Yes
deployment_name string The Conversational Language Understanding project deployment to be called. Yes

Translator Name Type Description Required
connection CustomConnection The created connection to an Azure AI Translator resource. Yes
text string The input text. Yes
to list[string] The languages to translate the input text to. Yes
source_language string The language of the input text. No
category string The category (domain) of the translation. This parameter is used to get translations from a customized system built with Custom Translator. Default value is general. No
text_type string (enum) The type of the text being translated. Possible values are plain (default) or html. No

Outputs

  • When the input parameter parse_response is set to False (default value), the full API JSON response will be returned (as a dict object).
  • When the input parameter parse_response is set to True, the full API JSON response will be parsed to extract the single task result associated with the tool's given skill. Output will depend on the skill (but will still be a dict object).
  • Note: for Conversational Language Understanding (CLU), output will be a list of responses (either full or parsed), one for each detected user utterance in the input.

Refer to Azure AI Language's REST API reference for details on API response format, specific task result formats, etc.

Sample Flows

Find example flows using the promptflow-azure-ai-language package here.

Contact

Please reach out to Azure AI Language ([email protected]) with any issues.


Integrations Tools Llmlingua Prompt Compression Tool (`docs/integrations/tools/llmlingua-prompt-compression-tool.md`)

LLMLingua Prompt Compression

Introduction

LLMLingua Prompt Compression tool enables you to speed up large language model's inference and enhance large language model's perceive of key information, compress the prompt with minimal performance loss.

Requirements

PyPI package: llmlingua-promptflow.

Prerequisite

Create a MaaS deployment for large language model in Azure model catalog. Take the Llama model as an example, you can learn how to deploy and consume Meta Llama models with model as a service by the guidance for Azure AI Studio.

Inputs

The tool accepts the following inputs:

Name Type Description Required
prompt string The prompt that needs to be compressed. Yes
myconn CustomConnection The created connection to a MaaS resource for calculating log probability. Yes
rate float The maximum compression rate target to be achieved. Default value is 0.5. No

Outputs

Return Type Description
string The resulting compressed prompt.

Sample Flows

Find example flows using the llmlingua-promptflow package here.

Contact

Please reach out to LLMLingua Team ([email protected]) with any issues.


Reference Tools Reference Aoai Gpt4 Turbo Vision (`docs/reference/tools-reference/aoai-gpt4-turbo-vision.md`)

Azure OpenAI GPT-4 Turbo with Vision

Introduction

Azure OpenAI GPT-4 Turbo with Vision tool enables you to leverage your AzureOpenAI GPT-4 Turbo with Vision model deployment to analyze images and provide textual responses to questions about them.

Prerequisites

  • Create AzureOpenAI resources

    Create Azure OpenAI resources with instruction

  • Create a GPT-4 Turbo with Vision deployment

    Browse to Azure OpenAI Studio and sign in with the credentials associated with your Azure OpenAI resource. During or after the sign-in workflow, select the appropriate directory, Azure subscription, and Azure OpenAI resource.

    Under Management select Deployments and Create a GPT-4 Turbo with Vision deployment by selecting model name: gpt-4 and model version vision-preview.

Connection

Setup connections to provisioned resources in prompt flow.

Type Name API KEY API Type API Version
AzureOpenAI Required Required Required Required

Inputs

Name Type Description Required
connection AzureOpenAI the AzureOpenAI connection to be used in the tool Yes
deployment_name string the language model to use Yes
prompt string The text prompt that the language model will use to generate it's response. Yes
max_tokens integer the maximum number of tokens to generate in the response. Default is 512. No
temperature float the randomness of the generated text. Default is 1. No
stop list the stopping sequence for the generated text. Default is null. No
top_p float the probability of using the top choice from the generated tokens. Default is 1. No
presence_penalty float value that controls the model's behavior with regards to repeating phrases. Default is 0. No
frequency_penalty float value that controls the model's behavior with regards to generating rare phrases. Default is 0. No
detail string configure how the model interprets and processes images, default is "auto". Read more No

Outputs

Return Type Description
string The text of one response of conversation

Reference Tools Reference Contentsafety Text Tool (`docs/reference/tools-reference/contentsafety_text_tool.md`)

Content Safety (Text)

Azure Content Safety is a content moderation service developed by Microsoft that help users detect harmful content from different modalities and languages. This tool is a wrapper for the Azure Content Safety Text API, which allows you to detect text content and get moderation results. See the Azure Content Safety for more information.

Requirements

  • For AzureML users, the tool is installed in default image, you can use the tool without extra installation.
  • For local users,
    pip install promptflow-tools

[!NOTE]
Content Safety (Text) tool is now incorporated into the latest promptflow-tools package. If you have previously installed the package promptflow-contentsafety, please uninstall it to avoid the duplication in your local tool list.

Prerequisites

  • Create an Azure Content Safety resource.
  • Add "Azure Content Safety" connection in prompt flow. Fill "API key" field with "Primary key" from "Keys and Endpoint" section of created resource.

Inputs

You can use the following parameters as inputs for this tool:

Name Type Description Required
text string The text that need to be moderated. Yes
hate_category string The moderation sensitivity for Hate category. You can choose from four options: disable, low_sensitivity, medium_sensitivity, or high_sensitivity. The disable option means no moderation for hate category. The other three options mean different degrees of strictness in filtering out hate content. The default option is medium_sensitivity. Yes
sexual_category string The moderation sensitivity for Sexual category. You can choose from four options: disable, low_sensitivity, medium_sensitivity, or high_sensitivity. The disable option means no moderation for sexual category. The other three options mean different degrees of strictness in filtering out sexual content. The default option is medium_sensitivity. Yes
self_harm_category string The moderation sensitivity for Self-harm category. You can choose from four options: disable, low_sensitivity, medium_sensitivity, or high_sensitivity. The disable option means no moderation for self-harm category. The other three options mean different degrees of strictness in filtering out self_harm content. The default option is medium_sensitivity. Yes
violence_category string The moderation sensitivity for Violence category. You can choose from four options: disable, low_sensitivity, medium_sensitivity, or high_sensitivity. The disable option means no moderation for violence category. The other three options mean different degrees of strictness in filtering out violence content. The default option is medium_sensitivity. Yes

For more information, please refer to Azure Content Safety

Outputs

The following is an example JSON format response returned by the tool:

Output

json
{
    "action_by_category": {
      "Hate": "Accept",
      "SelfHarm": "Accept",
      "Sexual": "Accept",
      "Violence": "Accept"
    },
    "suggested_action": "Accept"
  }

The action_by_category field gives you a binary value for each category: Accept or Reject. This value shows if the text meets the sensitivity level that you set in the request parameters for that category.

The suggested_action field gives you an overall recommendation based on the four categories. If any category has a Reject value, the suggested_action will be Reject as well.


Reference Tools Reference Embedding Tool (`docs/reference/tools-reference/embedding_tool.md`)

Embedding

Introduction

OpenAI's embedding models convert text into dense vector representations for various NLP tasks. See the OpenAI Embeddings API for more information.

Prerequisite

Create OpenAI resources:

**Connections**

Setup connections to provide resources in embedding tool.

Type Name API KEY API Type API Version
OpenAI Required Required - -
AzureOpenAI Required Required Required Required

Inputs

Name Type Description Required
input string the input text to embed Yes
connection string the connection for the embedding tool use to provide resources Yes
model/deployment_name string instance of the text-embedding engine to use. Fill in model name if you use OpenAI connection, or deployment name if use Azure OpenAI connection. Yes

Outputs

Return Type Description
list The vector representations for inputs

The following is an example response returned by the embedding tool:

Output

text
[-0.005744616035372019,
-0.007096089422702789,
-0.00563855143263936,
-0.005272455979138613,
-0.02355326898396015,
0.03955197334289551,
-0.014260607771575451,
-0.011810848489403725,
-0.023170066997408867,
-0.014739611186087132,
...]

Reference Tools Reference Faiss Index Lookup Tool (`docs/reference/tools-reference/faiss_index_lookup_tool.md`)

Faiss Index Lookup

Faiss Index Lookup is a tool tailored for querying within a user-provided Faiss-based vector store. In combination with our Large Language Model (LLM) tool, it empowers users to extract contextually relevant information from a domain knowledge base.

Requirements

  • For AzureML users, the tool is installed in default image, you can use the tool without extra installation.

  • For local users, if your index is stored in local path,

    pip install promptflow-vectordb

    if your index is stored in Azure storage,

    pip install promptflow-vectordb[azure]

Prerequisites

For AzureML users,

  • step 1. Prepare an accessible path on Azure Blob Storage. Here's the guide if a new storage account needs to be created: Azure Storage Account.

  • step 2. Create related Faiss-based index files on Azure Blob Storage. We support the LangChain format (index.faiss + index.pkl) for the index files, which can be prepared either by employing our promptflow-vectordb SDK or following the quick guide from LangChain documentation. Please refer to the instructions of An example code for creating Faiss index for building index using promptflow-vectordb SDK.

  • step 3. Based on where you put your own index files, the identity used by the promptflow runtime should be granted with certain roles. Please refer to Steps to assign an Azure role:

    Location Role
    workspace datastores or workspace default blob AzureML Data Scientist
    other blobs Storage Blob Data Reader

For local users,

  • Create Faiss-based index files in local path by only doing step 2 above.

Inputs

The tool accepts the following inputs:

Name Type Description Required
path string URL or path for the vector store.local path (for local users):<local_path_to_the_index_folder> Azure blob URL format (with [azure] extra installed):https://<account_name>.blob.core.windows.net/<container_name>/.AML datastore URL format (with [azure] extra installed):azureml://subscriptions/`<your_subscription>`/resourcegroups/`<your_resource_group>`/workspaces/`<your_workspace>`/data/`<data_path>`public http/https URL (for public demonstration):http(s):// Yes
vector list[float] The target vector to be queried, which can be generated by the LLM tool. Yes
top_k integer The count of top-scored entities to return. Default value is 3. No

Outputs

The following is an example for JSON format response returned by the tool, which includes the top-k scored entities. The entity follows a generic schema of vector search result provided by our promptflow-vectordb SDK. For the Faiss Index Search, the following fields are populated:

Field Name Type Description
text string Text of the entity
score float Distance between the entity and the query vector
metadata dict Customized key-value pairs provided by user when create the index

Output

json
[
  {
    "metadata": {
      "link": "http://sample_link_0",
      "title": "title0"
    },
    "original_entity": null,
    "score": 0,
    "text": "sample text #0",
    "vector": null
  },
  {
    "metadata": {
      "link": "http://sample_link_1",
      "title": "title1"
    },
    "original_entity": null,
    "score": 0.05000000447034836,
    "text": "sample text #1",
    "vector": null
  },
  {
    "metadata": {
      "link": "http://sample_link_2",
      "title": "title2"
    },
    "original_entity": null,
    "score": 0.20000001788139343,
    "text": "sample text #2",
    "vector": null
  }
]

Reference Tools Reference Llm Tool (`docs/reference/tools-reference/llm-tool.md`)

LLM

Introduction

Prompt flow LLM tool enables you to leverage widely used large language models like OpenAI, Azure OpenAI (AOAI), and models in Azure AI Studio model catalog for natural language processing.

[!NOTE]
The previous version of the LLM tool is now being deprecated. Please upgrade to latest promptflow-tools package to consume new llm tools.

Prompt flow provides a few different LLM APIs:

  • Completion: OpenAI's completion models generate text based on provided prompts.
  • Chat: OpenAI's chat models facilitate interactive conversations with text-based inputs and responses.

Prerequisite

Create OpenAI resources, Azure OpenAI resources or MaaS deployment with the LLM models (e.g.: llama2, mistral, cohere etc.) in Azure AI Studio model catalog:

  • OpenAI

    Sign up account OpenAI website

    Login and Find personal API key

  • Azure OpenAI (AOAI)

    Create Azure OpenAI resources with instruction

  • MaaS deployment

    Create MaaS deployment for models in Azure AI Studio model catalog with instruction

    You can create serverless connection to use this MaaS deployment.

**Connections**

Setup connections to provisioned resources in prompt flow.

Type Name API KEY API BASE API Type API Version
OpenAI Required Required - - -
AzureOpenAI Required Required Required Required Required
Serverless Required Required Required - -

Inputs

Text Completion

Name Type Description Required
prompt string text prompt that the language model will complete Yes
model, deployment_name string the language model to use Yes
max_tokens integer the maximum number of tokens to generate in the completion. Default is 16. No
temperature float the randomness of the generated text. Default is 1. No
stop list the stopping sequence for the generated text. Default is null. No
suffix string text appended to the end of the completion No
top_p float the probability of using the top choice from the generated tokens. Default is 1. No
logprobs integer the number of log probabilities to generate. Default is null. No
echo boolean value that indicates whether to echo back the prompt in the response. Default is false. No
presence_penalty float value that controls the model's behavior with regards to repeating phrases. Default is 0. No
frequency_penalty float value that controls the model's behavior with regards to generating rare phrases. Default is 0. No
best_of integer the number of best completions to generate. Default is 1. No
logit_bias dictionary the logit bias for the language model. Default is empty dictionary. No

Chat

Name Type Description Required
prompt string text prompt that the language model will response Yes
model, deployment_name string the language model to use Yes
max_tokens integer the maximum number of tokens to generate in the response. Default is inf. No
temperature float the randomness of the generated text. Default is 1. No
stop list the stopping sequence for the generated text. Default is null. No
top_p float the probability of using the top choice from the generated tokens. Default is 1. No
presence_penalty float value that controls the model's behavior with regards to repeating phrases. Default is 0. No
frequency_penalty float value that controls the model's behavior with regards to generating rare phrases. Default is 0. No
logit_bias dictionary the logit bias for the language model. Default is empty dictionary. No
tool_choice object value that controls which tool is called by the model. Default is null. No
tools list a list of tools the model may generate JSON inputs for. Default is null. No
response_format object an object specifying the format that the model must output. Default is null. No

Outputs

Return Type Description
string The text of one predicted completion or response of conversation

How to use LLM Tool?

  1. Setup and select the connections to OpenAI resources
  2. Configure LLM model api and its parameters
  3. Prepare the Prompt with guidance.

How to write a chat prompt?

To grasp the fundamentals of creating a chat prompt, begin with this section for an introductory understanding of jinja.

We offer a method to distinguish between different roles in a chat prompt, such as "system", "user", "assistant" and "tool". The "system", "user", "assistant" roles can have "name" and "content" properties. The "tool" role, however, should have "tool_call_id" and "content" properties. For an example of a tool chat prompt, please refer to Sample 3.

Sample 1

jinja
# system:
You are a helpful assistant.

{% for item in chat_history %}
# user:
{{item.inputs.question}}
# assistant:
{{item.outputs.answer}}
{% endfor %}

# user:
{{question}}

In LLM tool, the prompt is transformed to match the openai messages structure before sending to openai chat API.

text
[
    {
        "role": "system",
        "content": "You are a helpful assistant."
    },
    {
        "role": "user",
        "content": "<question-of-chat-history-round-1>"
    },
    {
        "role": "assistant",
        "content": "<answer-of-chat-history-round-1>"
    },
    ...
    {
        "role": "user",
        "content": "<question>"
    }
]

Sample 2

jinja
# system:
{# For role naming customization, the following syntax is used #}
## name:
Alice
## content:
You are a bot can tell good jokes.

In LLM tool, the prompt is transformed to match the openai messages structure before sending to openai chat API.

text
[
    {
        "role": "system",
        "name": "Alice",
        "content": "You are a bot can tell good jokes."
    }
]

Sample 3

This sample illustrates how to write a tool chat prompt.

jinja
# system:
You are a helpful assistant.

# user:
What is the current weather like in Boston?

# assistant:
{# The assistant message with 'tool_calls' must be followed by messages with role 'tool'. #}
## tool_calls:
{{llm_output.tool_calls}}

# tool:
{#
Messages with role 'tool' must be a response to a preceding message with 'tool_calls'.
Additionally, 'tool_call_id's should match ids of assistant message 'tool_calls'.
#}
## tool_call_id:
{{llm_output.tool_calls[0].id}}
## content:
{{tool-answer-of-last-question}}

# user:
{{question}}

In LLM tool, the prompt is transformed to match the openai messages structure before sending to openai chat API.

text
[
    {
        "role": "system",
        "content": "You are a helpful assistant."
    },
    {
        "role": "user",
        "content": "What is the current weather like in Boston?"
    },
    {
        "role": "assistant",
        "content": null,
        "function_call": null,
        "tool_calls": [
            {
                "id": "<tool-call-id-of-last-question>",
                "type": "function",
                "function": "<function-to-call-of-last-question>"
            }
        ]
    },
    {
        "role": "tool",
        "tool_call_id": "<tool-call-id-of-last-question>",
        "content": "<tool-answer-of-last-question>"
    }
    ...
    {
        "role": "user",
        "content": "<question>"
    }
]

Reference Tools Reference Llm Vision Tool (`docs/reference/tools-reference/llm-vision-tool.md`)

LLM Vision

Introduction

Prompt flow LLM vision tool enables you to leverage your AzureOpenAI GPT-4 Turbo or OpenAI's GPT-4 with vision to analyze images and provide textual responses to questions about them.

Prerequisites

Create OpenAI or Azure OpenAI resources:

  • OpenAI

    Sign up account OpenAI website

    Login and Find personal API key

  • Azure OpenAI (AOAI)

    Create Azure OpenAI resources with instruction

    Browse to Azure OpenAI Studio and sign in with the credentials associated with your Azure OpenAI resource. During or after the sign-in workflow, select the appropriate directory, Azure subscription, and Azure OpenAI resource.

    Under Management select Deployments and Create a GPT-4 Turbo with Vision deployment by selecting model name: gpt-4 and model version vision-preview.

**Connections**

Setup connections to provisioned resources in prompt flow.

Type Name API KEY API Type API Version
OpenAI Required Required - -
AzureOpenAI Required Required Required Required

Inputs

Name Type Description Required
model, deployment_name string the language model to use Yes
prompt string The text prompt that the language model will use to generate it's response. Yes
max_tokens integer the maximum number of tokens to generate in the response. Default is 512. No
temperature float the randomness of the generated text. Default is 1.