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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:52 +08:00
commit e768098d0e
4004 changed files with 2804145 additions and 0 deletions
@@ -0,0 +1,44 @@
---
resources: examples/tutorials/flow-deploy/create-service-with-flow
category: deployment
weight: 10
---
# Create service with flow
This example shows how to create a simple service with flow.
You can create your own service by utilize `flow-as-function`.
This folder contains a example on how to build a service with a flow.
Reference [here](./simple_score.py) for a minimal service example.
The output of score.py will be a json serialized dictionary.
You can use json parser to parse the output.
## 1. Start the service and put in background
```bash
nohup python simple_score.py &
# Note: added this to run in our CI pipeline, not needed for user.
sleep 10
```
## 2. Test the service with request
Executing the following command to send a request to execute a flow.
```bash
curl -X POST http://127.0.0.1:5000/score --header "Content-Type: application/json" --data '{"flow_input": "some_flow_input", "node_input": "some_node_input"}'
```
Sample output of the request:
```json
{
"output": {
"value": "some_flow_input"
}
}
```
Reference [here](./simple_score.py) for more.
@@ -0,0 +1,11 @@
from promptflow.core import tool
from promptflow.connections import AzureOpenAIConnection
@tool
def echo_connection(flow_input: str, node_input: str, connection: AzureOpenAIConnection):
print(f"Flow input: {flow_input}")
print(f"Node input: {node_input}")
print(f"Flow connection: {connection._to_dict()}")
# get from env var
return {"value": flow_input}
@@ -0,0 +1,18 @@
$schema: https://azuremlschemas.azureedge.net/promptflow/latest/Flow.schema.json
inputs:
flow_input:
type: string
outputs:
output:
type: object
reference: ${echo_connection.output}
nodes:
- name: echo_connection
type: python
source:
type: code
path: echo_connection.py
inputs:
flow_input: ${inputs.flow_input}
node_input: "dummy_node_input"
connection: open_ai_connection
@@ -0,0 +1,85 @@
import json
import logging
from flask import Flask, jsonify, request
from promptflow.client import load_flow
from promptflow.connections import AzureOpenAIConnection
from promptflow.entities import FlowContext
from promptflow.exceptions import SystemErrorException, UserErrorException
class SimpleScoreApp(Flask):
pass
app = SimpleScoreApp(__name__)
logging.basicConfig(format="%(threadName)s:%(message)s")
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
# load flow as a function, the function object can be shared accross threads.
f = load_flow("./echo_connection_flow/")
@app.errorhandler(Exception)
def handle_error(e):
if isinstance(e, UserErrorException):
return jsonify({"message": e.message, "additional_info": e.additional_info}), 400
elif isinstance(e, SystemErrorException):
return jsonify({"message": e.message, "additional_info": e.additional_info}), 500
else:
from promptflow._internal import ErrorResponse, ExceptionPresenter
# handle other unexpected errors, can use internal class to format them
# but interface may change in the future
presenter = ExceptionPresenter.create(e)
trace_back = presenter.formatted_traceback
resp = ErrorResponse(presenter.to_dict(include_debug_info=False))
response_code = resp.response_code
result = resp.to_simplified_dict()
result.update({"trace_back": trace_back})
return jsonify(result), response_code
@app.route("/health", methods=["GET"])
def health():
"""Check if the runtime is alive."""
return {"status": "Healthy"}
@app.route("/score", methods=["POST"])
def score():
"""process a flow request in the runtime."""
raw_data = request.get_data()
logger.info(f"Start loading request data '{raw_data}'.")
data = json.loads(raw_data)
# create a dummy connection object
# the connection object will only exist in memory and won't store in local db.
llm_connection = AzureOpenAIConnection(
name="llm_connection", api_key="[determined by request]", api_base="[determined by request]"
)
# configure flow contexts, create a new context object for each request to make sure they are thread safe.
f.context = FlowContext(
# override flow connections with connection object created above
connections={"echo_connection": {"connection": llm_connection}},
# override the flow nodes' inputs or other flow configs, the overrides may come from the request
# **Note**: after this change, node "echo_connection" will take input node_input from request
overrides={"nodes.echo_connection.inputs.node_input": data["node_input"]} if "node_input" in data else {},
)
# data in request will be passed to flow as kwargs
result_dict = f(**data)
# Note: if specified streaming=True in the flow context, the result will be a generator
# reference promptflow.core._serving.response_creator.ResponseCreator on how to handle it in app.
return jsonify(result_dict)
def create_app(**kwargs):
return app
if __name__ == "__main__":
# test this with curl -X POST http://127.0.0.1:5000/score --header "Content-Type: application/json" --data '{"flow_input": "some_flow_input", "node_input": "some_node_input"}' # noqa: E501
create_app().run(debug=True)