agent-bootstrap-kit 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_bootstrap_kit/__init__.py +18 -0
- agent_bootstrap_kit/cli.py +37 -0
- agent_bootstrap_kit/extractor.py +94 -0
- agent_bootstrap_kit/scripts/EXAM_DAY_REFERENCE.py +142 -0
- agent_bootstrap_kit/scripts/__init__.py +0 -0
- agent_bootstrap_kit/scripts/autogen/3_autogen_two_agent.py +75 -0
- agent_bootstrap_kit/scripts/autogen/4_autogen_tool_use.py +106 -0
- agent_bootstrap_kit/scripts/autogen/__init__.py +0 -0
- agent_bootstrap_kit/scripts/azure_ai_agent/7_azure_agent_thread.py +156 -0
- agent_bootstrap_kit/scripts/azure_ai_agent/__init__.py +0 -0
- agent_bootstrap_kit/scripts/plain_openai/1_multiturn_chat.py +82 -0
- agent_bootstrap_kit/scripts/plain_openai/2_simple_agent_tools.py +166 -0
- agent_bootstrap_kit/scripts/plain_openai/__init__.py +0 -0
- agent_bootstrap_kit/scripts/semantic_kernel/5_sk_basic_agent.py +135 -0
- agent_bootstrap_kit/scripts/semantic_kernel/6_sk_workflow.py +184 -0
- agent_bootstrap_kit/scripts/semantic_kernel/__init__.py +0 -0
- agent_bootstrap_kit/scripts/setup.sh +38 -0
- agent_bootstrap_kit-1.0.0.dist-info/METADATA +78 -0
- agent_bootstrap_kit-1.0.0.dist-info/RECORD +22 -0
- agent_bootstrap_kit-1.0.0.dist-info/WHEEL +5 -0
- agent_bootstrap_kit-1.0.0.dist-info/entry_points.txt +2 -0
- agent_bootstrap_kit-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SCRIPT 1: Plain OpenAI SDK — Multi-Turn Conversation Agent
|
|
3
|
+
===========================================================
|
|
4
|
+
What it does:
|
|
5
|
+
- Maintains a conversation history (list of messages)
|
|
6
|
+
- Sends the FULL history on every API call so the model remembers context
|
|
7
|
+
- You type messages, it replies, forever — until you type 'quit'
|
|
8
|
+
|
|
9
|
+
When to use this pattern:
|
|
10
|
+
- Chatbot, customer support bot, any conversational assistant
|
|
11
|
+
|
|
12
|
+
Key concept:
|
|
13
|
+
- messages = [ {role, content}, {role, content}, ... ]
|
|
14
|
+
- Always append both the user message AND the assistant reply to keep memory
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
from openai import OpenAI
|
|
19
|
+
from dotenv import load_dotenv
|
|
20
|
+
|
|
21
|
+
# ── Config ──────────────────────────────────────────────────
|
|
22
|
+
load_dotenv() # reads OPENAI_API_KEY from .env file
|
|
23
|
+
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
|
24
|
+
MODEL = "gpt-4o" # swap to gpt-4-turbo or gpt-3.5-turbo if needed
|
|
25
|
+
|
|
26
|
+
# ── System prompt — defines the agent's persona ─────────────
|
|
27
|
+
SYSTEM_PROMPT = """
|
|
28
|
+
You are a helpful assistant. Answer clearly and concisely.
|
|
29
|
+
If you don't know something, say so honestly.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
# ── Conversation history — this is how multi-turn memory works ──
|
|
33
|
+
conversation_history = [
|
|
34
|
+
{"role": "system", "content": SYSTEM_PROMPT}
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
def chat(user_message: str) -> str:
|
|
38
|
+
"""Send a message and get a reply. History is maintained automatically."""
|
|
39
|
+
|
|
40
|
+
# Step 1: Add the user's new message to history
|
|
41
|
+
conversation_history.append({
|
|
42
|
+
"role": "user",
|
|
43
|
+
"content": user_message
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
# Step 2: Send the FULL history to the API
|
|
47
|
+
response = client.chat.completions.create(
|
|
48
|
+
model=MODEL,
|
|
49
|
+
messages=conversation_history, # <-- full history, not just latest message
|
|
50
|
+
temperature=0.7,
|
|
51
|
+
max_tokens=1000
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Step 3: Extract the assistant's reply
|
|
55
|
+
assistant_reply = response.choices[0].message.content
|
|
56
|
+
|
|
57
|
+
# Step 4: Add the assistant's reply to history so next turn remembers it
|
|
58
|
+
conversation_history.append({
|
|
59
|
+
"role": "assistant",
|
|
60
|
+
"content": assistant_reply
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return assistant_reply
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# ── Main loop ────────────────────────────────────────────────
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
print("Multi-Turn Chat Agent started. Type 'quit' to exit.\n")
|
|
69
|
+
print("-" * 50)
|
|
70
|
+
|
|
71
|
+
while True:
|
|
72
|
+
user_input = input("\nYou: ").strip()
|
|
73
|
+
|
|
74
|
+
if not user_input:
|
|
75
|
+
continue
|
|
76
|
+
if user_input.lower() in ["quit", "exit", "q"]:
|
|
77
|
+
print("Goodbye!")
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
response = chat(user_input)
|
|
81
|
+
print(f"\nAssistant: {response}")
|
|
82
|
+
print(f"\n[History length: {len(conversation_history)} messages]")
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SCRIPT 2: Plain OpenAI SDK — Simple Agent with Tool Use (Function Calling)
|
|
3
|
+
==========================================================================
|
|
4
|
+
What it does:
|
|
5
|
+
- Defines Python functions as "tools" the model can call
|
|
6
|
+
- Model decides ON ITS OWN when to call a tool vs. answer directly
|
|
7
|
+
- Your code executes the tool and feeds the result back to the model
|
|
8
|
+
- Model uses the result to form the final answer
|
|
9
|
+
|
|
10
|
+
When to use this pattern:
|
|
11
|
+
- Agent that needs to look up data, do calculations, call APIs, etc.
|
|
12
|
+
|
|
13
|
+
Key concept:
|
|
14
|
+
- You define tools as JSON schemas (name + description + parameters)
|
|
15
|
+
- Model returns a tool_call instead of text when it wants to use a tool
|
|
16
|
+
- You run the actual Python function and return the result as a message
|
|
17
|
+
- Model then produces the final user-facing answer
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import json
|
|
22
|
+
from openai import OpenAI
|
|
23
|
+
from dotenv import load_dotenv
|
|
24
|
+
|
|
25
|
+
load_dotenv()
|
|
26
|
+
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
|
27
|
+
MODEL = "gpt-4o"
|
|
28
|
+
|
|
29
|
+
# ── Step 1: Define your actual Python tool functions ────────
|
|
30
|
+
def get_weather(city: str) -> str:
|
|
31
|
+
"""Simulated weather lookup. Replace with real API call if available."""
|
|
32
|
+
fake_weather = {
|
|
33
|
+
"london": "Cloudy, 15°C",
|
|
34
|
+
"new york": "Sunny, 22°C",
|
|
35
|
+
"tokyo": "Rainy, 18°C",
|
|
36
|
+
}
|
|
37
|
+
return fake_weather.get(city.lower(), f"Weather data not available for {city}")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def calculate(expression: str) -> str:
|
|
41
|
+
"""Safely evaluate a math expression like '12 * 7 + 3'."""
|
|
42
|
+
try:
|
|
43
|
+
result = eval(expression, {"__builtins__": {}}) # restricted eval
|
|
44
|
+
return str(result)
|
|
45
|
+
except Exception as e:
|
|
46
|
+
return f"Error: {e}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# ── Step 2: Describe the tools to OpenAI in JSON schema format ──
|
|
50
|
+
TOOLS = [
|
|
51
|
+
{
|
|
52
|
+
"type": "function",
|
|
53
|
+
"function": {
|
|
54
|
+
"name": "get_weather",
|
|
55
|
+
"description": "Get the current weather for a given city",
|
|
56
|
+
"parameters": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"properties": {
|
|
59
|
+
"city": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "The name of the city, e.g. 'London'"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"required": ["city"]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"type": "function",
|
|
70
|
+
"function": {
|
|
71
|
+
"name": "calculate",
|
|
72
|
+
"description": "Evaluate a mathematical expression",
|
|
73
|
+
"parameters": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"expression": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "A math expression like '12 * 7 + 3'"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"required": ["expression"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
# Map tool names to actual Python functions
|
|
88
|
+
TOOL_MAP = {
|
|
89
|
+
"get_weather": get_weather,
|
|
90
|
+
"calculate": calculate,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ── Step 3: Agent loop — handles tool calls automatically ────
|
|
95
|
+
def run_agent(user_message: str) -> str:
|
|
96
|
+
"""
|
|
97
|
+
Agentic loop:
|
|
98
|
+
1. Send message to model
|
|
99
|
+
2. If model wants to call a tool → execute it → send result back
|
|
100
|
+
3. Repeat until model gives a final text answer
|
|
101
|
+
"""
|
|
102
|
+
messages = [
|
|
103
|
+
{"role": "system", "content": "You are a helpful assistant. Use tools when appropriate."},
|
|
104
|
+
{"role": "user", "content": user_message}
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
print(f"\nUser: {user_message}")
|
|
108
|
+
|
|
109
|
+
while True:
|
|
110
|
+
# Call the model
|
|
111
|
+
response = client.chat.completions.create(
|
|
112
|
+
model=MODEL,
|
|
113
|
+
messages=messages,
|
|
114
|
+
tools=TOOLS,
|
|
115
|
+
tool_choice="auto" # model decides whether to use a tool
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
message = response.choices[0].message
|
|
119
|
+
finish_reason = response.choices[0].finish_reason
|
|
120
|
+
|
|
121
|
+
# ── Case A: Model wants to use a tool ───────────────
|
|
122
|
+
if finish_reason == "tool_calls":
|
|
123
|
+
print(f"\n[Agent is calling tools...]")
|
|
124
|
+
|
|
125
|
+
# Add model's tool-call message to history
|
|
126
|
+
messages.append(message)
|
|
127
|
+
|
|
128
|
+
# Execute each tool the model requested
|
|
129
|
+
for tool_call in message.tool_calls:
|
|
130
|
+
tool_name = tool_call.function.name
|
|
131
|
+
tool_args = json.loads(tool_call.function.arguments)
|
|
132
|
+
|
|
133
|
+
print(f" → Tool: {tool_name}({tool_args})")
|
|
134
|
+
|
|
135
|
+
# Run the actual Python function
|
|
136
|
+
tool_result = TOOL_MAP[tool_name](**tool_args)
|
|
137
|
+
print(f" ← Result: {tool_result}")
|
|
138
|
+
|
|
139
|
+
# Feed the result back into the conversation
|
|
140
|
+
messages.append({
|
|
141
|
+
"role": "tool",
|
|
142
|
+
"tool_call_id": tool_call.id,
|
|
143
|
+
"content": str(tool_result)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
# Loop again — model will now form the final answer
|
|
147
|
+
|
|
148
|
+
# ── Case B: Model has a final answer ────────────────
|
|
149
|
+
elif finish_reason == "stop":
|
|
150
|
+
final_answer = message.content
|
|
151
|
+
print(f"\nAssistant: {final_answer}")
|
|
152
|
+
return final_answer
|
|
153
|
+
|
|
154
|
+
else:
|
|
155
|
+
print(f"Unexpected finish_reason: {finish_reason}")
|
|
156
|
+
break
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# ── Main ─────────────────────────────────────────────────────
|
|
160
|
+
if __name__ == "__main__":
|
|
161
|
+
print("Tool-Use Agent. Example queries:\n")
|
|
162
|
+
run_agent("What's the weather like in London?")
|
|
163
|
+
print("\n" + "="*50)
|
|
164
|
+
run_agent("What is 347 multiplied by 28?")
|
|
165
|
+
print("\n" + "="*50)
|
|
166
|
+
run_agent("Is it raining in Tokyo, and if so what's 15 percent of 200?")
|
|
File without changes
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SCRIPT 5: Semantic Kernel — Basic Agent with Plugin (Tool)
|
|
3
|
+
==========================================================
|
|
4
|
+
What it does:
|
|
5
|
+
- Creates a Semantic Kernel kernel (the core engine)
|
|
6
|
+
- Adds an OpenAI Chat Completion service
|
|
7
|
+
- Defines a Plugin (SK's name for a set of tools/functions)
|
|
8
|
+
- Runs a multi-turn conversation where the model can call plugin functions
|
|
9
|
+
|
|
10
|
+
When to use this pattern:
|
|
11
|
+
- Microsoft SK is common in enterprise/.NET environments
|
|
12
|
+
- Good for structured workflows and plugin-based agents
|
|
13
|
+
|
|
14
|
+
Key concepts:
|
|
15
|
+
- kernel : the central object — configure services and plugins here
|
|
16
|
+
- Plugin : a class with @kernel_function decorated methods = tools
|
|
17
|
+
- invoke() : call a specific function directly
|
|
18
|
+
- chat loop : use ChatCompletionAgent or manual chat_history for multi-turn
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import asyncio
|
|
23
|
+
from dotenv import load_dotenv
|
|
24
|
+
|
|
25
|
+
# Semantic Kernel imports
|
|
26
|
+
from semantic_kernel import Kernel
|
|
27
|
+
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
|
|
28
|
+
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
|
|
29
|
+
from semantic_kernel.connectors.ai.open_ai import OpenAIChatPromptExecutionSettings
|
|
30
|
+
from semantic_kernel.contents.chat_history import ChatHistory
|
|
31
|
+
from semantic_kernel.core_plugins import TimePlugin
|
|
32
|
+
from semantic_kernel.functions import kernel_function
|
|
33
|
+
|
|
34
|
+
load_dotenv()
|
|
35
|
+
|
|
36
|
+
# ── Step 1: Create and configure the Kernel ─────────────────
|
|
37
|
+
kernel = Kernel()
|
|
38
|
+
|
|
39
|
+
# Add OpenAI as the AI service
|
|
40
|
+
kernel.add_service(
|
|
41
|
+
OpenAIChatCompletion(
|
|
42
|
+
service_id="openai_chat",
|
|
43
|
+
ai_model_id="gpt-4o",
|
|
44
|
+
api_key=os.getenv("OPENAI_API_KEY"),
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# ── Step 2: Define a custom Plugin (set of tools) ────────────
|
|
50
|
+
class WeatherPlugin:
|
|
51
|
+
"""A simple plugin that provides weather information."""
|
|
52
|
+
|
|
53
|
+
@kernel_function(
|
|
54
|
+
name="get_weather",
|
|
55
|
+
description="Get the current weather for a specific city"
|
|
56
|
+
)
|
|
57
|
+
def get_weather(self, city: str) -> str:
|
|
58
|
+
"""Returns simulated weather data for a city."""
|
|
59
|
+
weather_data = {
|
|
60
|
+
"london": "Overcast, 14°C, humidity 80%",
|
|
61
|
+
"new york": "Sunny, 23°C, humidity 45%",
|
|
62
|
+
"tokyo": "Light rain, 19°C, humidity 70%",
|
|
63
|
+
"mumbai": "Hot and humid, 33°C, humidity 85%",
|
|
64
|
+
}
|
|
65
|
+
return weather_data.get(
|
|
66
|
+
city.lower(),
|
|
67
|
+
f"Weather data not available for {city}"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
@kernel_function(
|
|
71
|
+
name="get_forecast",
|
|
72
|
+
description="Get a 3-day weather forecast for a city"
|
|
73
|
+
)
|
|
74
|
+
def get_forecast(self, city: str) -> str:
|
|
75
|
+
"""Returns a simulated 3-day forecast."""
|
|
76
|
+
return (
|
|
77
|
+
f"3-day forecast for {city}: "
|
|
78
|
+
f"Day 1: Cloudy 16°C | Day 2: Sunny 20°C | Day 3: Rain 13°C"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# ── Step 3: Register plugins on the kernel ───────────────────
|
|
83
|
+
kernel.add_plugin(WeatherPlugin(), plugin_name="weather")
|
|
84
|
+
kernel.add_plugin(TimePlugin(), plugin_name="time") # built-in SK plugin
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ── Step 4: Multi-turn chat loop with auto function calling ──
|
|
88
|
+
async def run_chat():
|
|
89
|
+
# Get the chat completion service
|
|
90
|
+
chat_service = kernel.get_service("openai_chat")
|
|
91
|
+
|
|
92
|
+
# Settings: allow the model to auto-call our plugin functions
|
|
93
|
+
settings = OpenAIChatPromptExecutionSettings(
|
|
94
|
+
service_id="openai_chat",
|
|
95
|
+
function_choice_behavior=FunctionChoiceBehavior.Auto(
|
|
96
|
+
filters={"included_plugins": ["weather", "time"]}
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Chat history maintains multi-turn memory
|
|
101
|
+
chat_history = ChatHistory()
|
|
102
|
+
chat_history.add_system_message(
|
|
103
|
+
"You are a helpful weather assistant. "
|
|
104
|
+
"Use the weather plugin to answer questions about weather. "
|
|
105
|
+
"Be friendly and informative."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
print("Semantic Kernel Weather Agent. Type 'quit' to exit.\n")
|
|
109
|
+
print("-" * 50)
|
|
110
|
+
|
|
111
|
+
while True:
|
|
112
|
+
user_input = input("\nYou: ").strip()
|
|
113
|
+
if not user_input or user_input.lower() in ["quit", "exit"]:
|
|
114
|
+
print("Goodbye!")
|
|
115
|
+
break
|
|
116
|
+
|
|
117
|
+
# Add user message to history
|
|
118
|
+
chat_history.add_user_message(user_input)
|
|
119
|
+
|
|
120
|
+
# Get response — SK will auto-invoke plugin functions if needed
|
|
121
|
+
response = await chat_service.get_chat_message_content(
|
|
122
|
+
chat_history=chat_history,
|
|
123
|
+
settings=settings,
|
|
124
|
+
kernel=kernel,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
print(f"\nAssistant: {response}")
|
|
128
|
+
|
|
129
|
+
# Add assistant response to history
|
|
130
|
+
chat_history.add_assistant_message(str(response))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ── Main ─────────────────────────────────────────────────────
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
asyncio.run(run_chat())
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SCRIPT 6: Semantic Kernel — Sequential Workflow (Step-by-Step Plan)
|
|
3
|
+
====================================================================
|
|
4
|
+
What it does:
|
|
5
|
+
- Manually chains multiple SK functions into a workflow pipeline
|
|
6
|
+
- Each step's output feeds into the next step
|
|
7
|
+
- Models a real-world multi-step processing workflow
|
|
8
|
+
|
|
9
|
+
When to use this pattern:
|
|
10
|
+
- Document processing pipelines
|
|
11
|
+
- Data transformation workflows
|
|
12
|
+
- Any "do A, then use A's output to do B" scenario
|
|
13
|
+
|
|
14
|
+
Key concepts:
|
|
15
|
+
- kernel.invoke() : run one function
|
|
16
|
+
- KernelArguments : pass inputs and carry context between steps
|
|
17
|
+
- Prompt functions : define LLM steps as string templates with {{$input}}
|
|
18
|
+
- Native functions : define Python logic steps using @kernel_function
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import asyncio
|
|
23
|
+
from dotenv import load_dotenv
|
|
24
|
+
|
|
25
|
+
from semantic_kernel import Kernel
|
|
26
|
+
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
|
|
27
|
+
from semantic_kernel.functions import kernel_function, KernelArguments
|
|
28
|
+
from semantic_kernel.prompt_template import PromptTemplateConfig
|
|
29
|
+
|
|
30
|
+
load_dotenv()
|
|
31
|
+
|
|
32
|
+
# ── Setup kernel ─────────────────────────────────────────────
|
|
33
|
+
kernel = Kernel()
|
|
34
|
+
kernel.add_service(
|
|
35
|
+
OpenAIChatCompletion(
|
|
36
|
+
service_id="openai_chat",
|
|
37
|
+
ai_model_id="gpt-4o",
|
|
38
|
+
api_key=os.getenv("OPENAI_API_KEY"),
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ── Define workflow steps as a Plugin ────────────────────────
|
|
44
|
+
class DocumentWorkflowPlugin:
|
|
45
|
+
"""
|
|
46
|
+
Simulates a document processing workflow:
|
|
47
|
+
Step 1 (native): Validate/clean the input text
|
|
48
|
+
Step 2 (prompt): Summarize the text using AI
|
|
49
|
+
Step 3 (prompt): Extract key action items using AI
|
|
50
|
+
Step 4 (native): Format the final output
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
@kernel_function(
|
|
54
|
+
name="validate_input",
|
|
55
|
+
description="Validate and clean the input text"
|
|
56
|
+
)
|
|
57
|
+
def validate_input(self, text: str) -> str:
|
|
58
|
+
"""Native (Python) function — no LLM needed."""
|
|
59
|
+
if not text or len(text.strip()) < 10:
|
|
60
|
+
raise ValueError("Input text is too short or empty")
|
|
61
|
+
# Clean up whitespace
|
|
62
|
+
cleaned = " ".join(text.split())
|
|
63
|
+
print(f" [Step 1] Input validated. Length: {len(cleaned)} chars")
|
|
64
|
+
return cleaned
|
|
65
|
+
|
|
66
|
+
@kernel_function(
|
|
67
|
+
name="format_output",
|
|
68
|
+
description="Format the final workflow result into a structured report"
|
|
69
|
+
)
|
|
70
|
+
def format_output(self, summary: str, action_items: str, original_length: int) -> str:
|
|
71
|
+
"""Native (Python) function — formats the final result."""
|
|
72
|
+
report = f"""
|
|
73
|
+
╔══════════════════════════════════════════════╗
|
|
74
|
+
║ DOCUMENT PROCESSING REPORT ║
|
|
75
|
+
╚══════════════════════════════════════════════╝
|
|
76
|
+
|
|
77
|
+
ORIGINAL LENGTH : {original_length} characters
|
|
78
|
+
|
|
79
|
+
SUMMARY
|
|
80
|
+
───────
|
|
81
|
+
{summary.strip()}
|
|
82
|
+
|
|
83
|
+
ACTION ITEMS
|
|
84
|
+
────────────
|
|
85
|
+
{action_items.strip()}
|
|
86
|
+
|
|
87
|
+
╔══════════════════════════════════════════════╗
|
|
88
|
+
║ END OF REPORT ║
|
|
89
|
+
╚══════════════════════════════════════════════╝
|
|
90
|
+
"""
|
|
91
|
+
return report
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ── Register plugin ──────────────────────────────────────────
|
|
95
|
+
kernel.add_plugin(DocumentWorkflowPlugin(), plugin_name="workflow")
|
|
96
|
+
|
|
97
|
+
# ── Register AI-powered prompt functions ─────────────────────
|
|
98
|
+
|
|
99
|
+
# Summarize function — uses LLM
|
|
100
|
+
summarize_function = kernel.add_function(
|
|
101
|
+
plugin_name="workflow",
|
|
102
|
+
function_name="summarize",
|
|
103
|
+
prompt="Summarize the following text in 3-4 sentences:\n\n{{$input}}",
|
|
104
|
+
prompt_template_settings=PromptTemplateConfig(
|
|
105
|
+
template="Summarize the following text in 3-4 sentences:\n\n{{$input}}"
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Extract action items function — uses LLM
|
|
110
|
+
extract_actions_function = kernel.add_function(
|
|
111
|
+
plugin_name="workflow",
|
|
112
|
+
function_name="extract_actions",
|
|
113
|
+
prompt="""From the following text, extract any action items, tasks, or next steps.
|
|
114
|
+
Format as a numbered list. If none found, say 'No action items identified.'
|
|
115
|
+
|
|
116
|
+
Text: {{$input}}""",
|
|
117
|
+
prompt_template_settings=PromptTemplateConfig(
|
|
118
|
+
template="""From the following text, extract any action items, tasks, or next steps.
|
|
119
|
+
Format as a numbered list. If none found, say 'No action items identified.'
|
|
120
|
+
|
|
121
|
+
Text: {{$input}}"""
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# ── Run the workflow ─────────────────────────────────────────
|
|
127
|
+
async def run_workflow(input_text: str):
|
|
128
|
+
print("\nStarting Document Processing Workflow...")
|
|
129
|
+
print("=" * 50)
|
|
130
|
+
|
|
131
|
+
# Step 1: Validate input (native Python)
|
|
132
|
+
print("\n[Step 1] Validating input...")
|
|
133
|
+
step1_result = await kernel.invoke(
|
|
134
|
+
kernel.plugins["workflow"]["validate_input"],
|
|
135
|
+
KernelArguments(text=input_text)
|
|
136
|
+
)
|
|
137
|
+
clean_text = str(step1_result)
|
|
138
|
+
original_length = len(clean_text)
|
|
139
|
+
|
|
140
|
+
# Step 2: Summarize with AI
|
|
141
|
+
print("[Step 2] Generating summary with AI...")
|
|
142
|
+
step2_result = await kernel.invoke(
|
|
143
|
+
kernel.plugins["workflow"]["summarize"],
|
|
144
|
+
KernelArguments(input=clean_text)
|
|
145
|
+
)
|
|
146
|
+
summary = str(step2_result)
|
|
147
|
+
|
|
148
|
+
# Step 3: Extract action items with AI
|
|
149
|
+
print("[Step 3] Extracting action items with AI...")
|
|
150
|
+
step3_result = await kernel.invoke(
|
|
151
|
+
kernel.plugins["workflow"]["extract_actions"],
|
|
152
|
+
KernelArguments(input=clean_text)
|
|
153
|
+
)
|
|
154
|
+
action_items = str(step3_result)
|
|
155
|
+
|
|
156
|
+
# Step 4: Format final output (native Python)
|
|
157
|
+
print("[Step 4] Formatting final report...")
|
|
158
|
+
final_result = await kernel.invoke(
|
|
159
|
+
kernel.plugins["workflow"]["format_output"],
|
|
160
|
+
KernelArguments(
|
|
161
|
+
summary=summary,
|
|
162
|
+
action_items=action_items,
|
|
163
|
+
original_length=original_length
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
print("\n" + str(final_result))
|
|
168
|
+
return str(final_result)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# ── Main ─────────────────────────────────────────────────────
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
sample_document = """
|
|
174
|
+
Our Q3 product review meeting covered several important topics.
|
|
175
|
+
The mobile app team needs to fix the login bug by end of week.
|
|
176
|
+
Revenue is up 15% compared to last quarter, driven by enterprise sales.
|
|
177
|
+
John needs to prepare the board presentation by Friday.
|
|
178
|
+
The infrastructure team should upgrade the database servers before the holiday freeze.
|
|
179
|
+
Customer satisfaction scores improved after the recent UX redesign.
|
|
180
|
+
Sarah will follow up with the three key enterprise clients who haven't renewed.
|
|
181
|
+
We agreed to hold a retrospective next Monday at 10am.
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
asyncio.run(run_workflow(sample_document))
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ============================================================
|
|
3
|
+
# BOOTSTRAP SETUP SCRIPT
|
|
4
|
+
# Run this first on the VM to install all required packages
|
|
5
|
+
# Usage: bash setup.sh
|
|
6
|
+
# ============================================================
|
|
7
|
+
|
|
8
|
+
echo "Installing all required packages..."
|
|
9
|
+
|
|
10
|
+
# Core OpenAI SDK
|
|
11
|
+
pip install openai --quiet
|
|
12
|
+
|
|
13
|
+
# AutoGen (Microsoft multi-agent framework)
|
|
14
|
+
pip install pyautogen --quiet
|
|
15
|
+
|
|
16
|
+
# Semantic Kernel (Microsoft SK framework)
|
|
17
|
+
pip install semantic-kernel --quiet
|
|
18
|
+
|
|
19
|
+
# Azure AI Agent Service SDK
|
|
20
|
+
pip install azure-ai-projects azure-identity --quiet
|
|
21
|
+
|
|
22
|
+
# Utility
|
|
23
|
+
pip install python-dotenv --quiet
|
|
24
|
+
|
|
25
|
+
echo ""
|
|
26
|
+
echo "All packages installed successfully!"
|
|
27
|
+
echo ""
|
|
28
|
+
echo "Next step: copy your OpenAI API key into a .env file:"
|
|
29
|
+
echo " OPENAI_API_KEY=sk-..."
|
|
30
|
+
echo ""
|
|
31
|
+
echo "Then run any of the example scripts:"
|
|
32
|
+
echo " python plain_openai/1_multiturn_chat.py"
|
|
33
|
+
echo " python plain_openai/2_simple_agent_tools.py"
|
|
34
|
+
echo " python autogen/3_autogen_two_agent.py"
|
|
35
|
+
echo " python autogen/4_autogen_tool_use.py"
|
|
36
|
+
echo " python semantic_kernel/5_sk_basic_agent.py"
|
|
37
|
+
echo " python semantic_kernel/6_sk_planner.py"
|
|
38
|
+
echo " python azure_ai_agent/7_azure_agent_thread.py"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-bootstrap-kit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: OpenAI agent bootstrap scripts for assessments
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: openai>=1.0.0
|
|
9
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
10
|
+
Requires-Dist: pyautogen>=0.2.0
|
|
11
|
+
Requires-Dist: semantic-kernel>=1.0.0
|
|
12
|
+
Requires-Dist: azure-ai-projects>=1.0.0
|
|
13
|
+
Requires-Dist: azure-identity>=1.0.0
|
|
14
|
+
|
|
15
|
+
# agent-bootstrap-kit
|
|
16
|
+
|
|
17
|
+
Bootstrap scripts for building OpenAI agents — multi-turn chat, tool use, AutoGen, Semantic Kernel, and Azure AI Agent Service.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install agent-bootstrap-kit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Extract scripts to your current folder
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
agent-bootstrap
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or in Python:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from agent_bootstrap_kit import extract
|
|
35
|
+
extract()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## What gets extracted
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
plain_openai/
|
|
42
|
+
1_multiturn_chat.py # Multi-turn conversation agent
|
|
43
|
+
2_simple_agent_tools.py # Agent with tool/function calling
|
|
44
|
+
|
|
45
|
+
autogen/
|
|
46
|
+
3_autogen_two_agent.py # AutoGen two-agent conversation
|
|
47
|
+
4_autogen_tool_use.py # AutoGen agent with tools
|
|
48
|
+
|
|
49
|
+
semantic_kernel/
|
|
50
|
+
5_sk_basic_agent.py # Semantic Kernel agent with plugin
|
|
51
|
+
6_sk_workflow.py # Semantic Kernel multi-step pipeline
|
|
52
|
+
|
|
53
|
+
azure_ai_agent/
|
|
54
|
+
7_azure_agent_thread.py # Azure AI Agent Service (thread-based)
|
|
55
|
+
|
|
56
|
+
EXAM_DAY_REFERENCE.py # Quick reference — which script to use when
|
|
57
|
+
setup.sh # Install all dependencies in one command
|
|
58
|
+
.env.template # Copy → .env, add your API key
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick start after extraction
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 1. Add your API key
|
|
65
|
+
cp .env.template .env
|
|
66
|
+
# Edit .env: OPENAI_API_KEY=sk-...
|
|
67
|
+
|
|
68
|
+
# 2. Install dependencies
|
|
69
|
+
bash setup.sh
|
|
70
|
+
|
|
71
|
+
# 3. Run a script
|
|
72
|
+
python plain_openai/1_multiturn_chat.py
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Requirements
|
|
76
|
+
|
|
77
|
+
- Python 3.9+
|
|
78
|
+
- An OpenAI API key
|