e768098d0e
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
109 lines
4.0 KiB
Python
109 lines
4.0 KiB
Python
import asyncio
|
|
import os
|
|
from dataclasses import dataclass
|
|
|
|
from dotenv import load_dotenv
|
|
from typing_extensions import Never
|
|
|
|
from agent_framework import Agent, Executor, WorkflowBuilder, WorkflowContext, handler
|
|
from agent_framework.openai import OpenAIChatClient
|
|
|
|
load_dotenv()
|
|
|
|
_CLASSIFY_SYSTEM_PROMPT = """\
|
|
There is a search bar in the mall APP and users can enter any query in the search bar.
|
|
|
|
The user may want to search for orders, view product information, or seek recommended products.
|
|
|
|
Therefore, please classify user intentions into the following three types \
|
|
according to the query: product_recommendation, order_search, product_info
|
|
|
|
Please note that only the above three situations can be returned, and try not to include other return values."""
|
|
|
|
|
|
@dataclass
|
|
class ClassifiedQuery:
|
|
query: str
|
|
intention: str
|
|
|
|
|
|
class ClassifyExecutor(Executor):
|
|
def __init__(self, **kwargs):
|
|
super().__init__(**kwargs)
|
|
client = OpenAIChatClient(
|
|
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
|
|
model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
|
|
api_key=os.environ["AZURE_OPENAI_API_KEY"],
|
|
)
|
|
self._agent = Agent(
|
|
client=client,
|
|
name="ClassifyAgent",
|
|
instructions=_CLASSIFY_SYSTEM_PROMPT,
|
|
)
|
|
|
|
@handler
|
|
async def classify(self, query: str, ctx: WorkflowContext[ClassifiedQuery]) -> None:
|
|
response = await self._agent.run(f"The user's query is {query}")
|
|
llm_result = response.text
|
|
intentions_list = ["order_search", "product_info", "product_recommendation"]
|
|
matches = [i for i in intentions_list if i in llm_result.lower()]
|
|
intention = matches[0] if matches else "unknown"
|
|
await ctx.send_message(ClassifiedQuery(query=query, intention=intention))
|
|
|
|
|
|
class OrderSearchExecutor(Executor):
|
|
@handler
|
|
async def search(self, msg: ClassifiedQuery, ctx: WorkflowContext[Never, str]) -> None:
|
|
await ctx.yield_output("Your order is being mailed, please wait patiently.")
|
|
|
|
|
|
class ProductInfoExecutor(Executor):
|
|
@handler
|
|
async def info(self, msg: ClassifiedQuery, ctx: WorkflowContext[Never, str]) -> None:
|
|
await ctx.yield_output("This product is produced by Microsoft.")
|
|
|
|
|
|
class ProductRecommendationExecutor(Executor):
|
|
@handler
|
|
async def recommend(self, msg: ClassifiedQuery, ctx: WorkflowContext[Never, str]) -> None:
|
|
await ctx.yield_output(
|
|
"I recommend promptflow to you, which can solve your problem very well."
|
|
)
|
|
|
|
|
|
class DefaultExecutor(Executor):
|
|
@handler
|
|
async def default(self, msg: ClassifiedQuery, ctx: WorkflowContext[Never, str]) -> None:
|
|
await ctx.yield_output("Sorry, no results matching your search were found.")
|
|
|
|
|
|
def create_workflow():
|
|
"""Create a fresh workflow instance.
|
|
|
|
MAF workflows do not support concurrent execution, so each
|
|
concurrent caller needs its own workflow instance.
|
|
"""
|
|
_classify = ClassifyExecutor(id="classify")
|
|
_order = OrderSearchExecutor(id="order_search")
|
|
_product = ProductInfoExecutor(id="product_info")
|
|
_recommend = ProductRecommendationExecutor(id="product_recommendation")
|
|
_default = DefaultExecutor(id="default")
|
|
return (
|
|
WorkflowBuilder(name="ConditionalSwitchWorkflow", start_executor=_classify)
|
|
.add_edge(_classify, _order, condition=lambda m: m.intention == "order_search")
|
|
.add_edge(_classify, _product, condition=lambda m: m.intention == "product_info")
|
|
.add_edge(_classify, _recommend, condition=lambda m: m.intention == "product_recommendation")
|
|
.add_edge(_classify, _default, condition=lambda m: m.intention == "unknown")
|
|
.build()
|
|
)
|
|
|
|
|
|
async def main():
|
|
workflow = create_workflow()
|
|
result = await workflow.run("When will my order be shipped?")
|
|
print(f"Response: {result.get_outputs()[0]}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|