-
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathcoroutine_example.cpp
More file actions
275 lines (228 loc) · 10.1 KB
/
Copy pathcoroutine_example.cpp
File metadata and controls
275 lines (228 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/**
* @example coroutine_example.cpp
* @brief Coroutine Example
* @version 0.1
* @date 2025-07-20
*
* @copyright Copyright (c) 2026 Edge AI, LLC. All rights reserved.
*
*/
#include <agents-cpp/agents/autonomous_agent.h>
#include <agents-cpp/config_loader.h>
#include <agents-cpp/logger.h>
#include <agents-cpp/tools/tool_registry.h>
#include <iostream>
using namespace agents;
// Simple callback to print agent steps
void stepCallback(const AutonomousAgent::Step& step) {
Logger::info("Step: {}", step.description);
Logger::info("Status: {}", step.status);
if (step.success) {
Logger::info("Result: {}", step.result.dump(2));
} else {
Logger::error("Failed!");
}
Logger::info("--------------------------------------");
}
// Simple callback for human-in-the-loop
bool humanApproval(const std::string& message, const JsonObject& context, std::string& modifications) {
(void)modifications;
if (!context.empty()) {
Logger::info("Context: {}", context.dump(2));
}
Logger::info("\n{}", message);
Logger::info("Approve this step? (y/n): ");
char response;
std::cin >> response;
return (response == 'y' || response == 'Y');
}
// Example coroutine that performs a multi-step task using tools
Task<JsonObject> performResearchTask(std::shared_ptr<Context> context, const std::string& topic) {
Logger::info("Starting research on topic: {}", topic);
// Perform a search to get initial information
auto search_tool = tools::createWebSearchTool(context->getLLM());
auto search_result = co_await context->executeTool("web_search", {{"query", topic}});
// Extract key points from the search result
Logger::info("Extracting key points from search results...");
auto extract_prompt = "Extract the key points from this search result about " + topic + ":\n\n" + search_result.content;
auto extract_response = co_await context->chat(extract_prompt);
// Get more detailed information from Wikipedia
Logger::info("Getting more information from Wikipedia...");
auto wiki_tool = tools::createWikipediaTool();
auto wiki_result = co_await context->executeTool("wikipedia", {{"query", topic}});
// Combine and summarize all information
Logger::info("Summarizing all information...");
auto summarize_prompt = "Synthesize and summarize the following information about " + topic + ":\n\n";
summarize_prompt += "Key Points:\n" + extract_response.content + "\n\n";
summarize_prompt += "Wikipedia Information:\n" + wiki_result.content;
auto summary_response = co_await context->chat(summarize_prompt);
// Provide a final answer
JsonObject result = {
{"topic", topic},
{"summary", summary_response.content},
{"search_results", search_result.content},
{"wiki_results", wiki_result.content}
};
Logger::info("Research complete!");
co_return result;
}
// Example coroutine that generates content in parallel
Task<JsonObject> generateContentInParallel(std::shared_ptr<Context> context, const std::string& topic) {
Logger::info("Generating content for topic: {}", topic);
// Create a prompt for the introduction
std::string intro_prompt = "Write an introduction paragraph for an article about " + topic + ".";
// Create a prompt for the main body
std::string body_prompt = "Write three key points about " + topic + " with detailed explanations.";
// Create a prompt for the conclusion
std::string conclusion_prompt = "Write a conclusion paragraph for an article about " + topic + ".";
// Launch all tasks concurrently
auto intro_task = context->chat(intro_prompt);
auto body_task = context->chat(body_prompt);
auto conclusion_task = context->chat(conclusion_prompt);
// Await all tasks (this happens in parallel)
auto intro_response = co_await std::move(intro_task);
auto body_response = co_await std::move(body_task);
auto conclusion_response = co_await std::move(conclusion_task);
// Now we have all the pieces, combine them
std::string article = intro_response.content + "\n\n" + body_response.content + "\n\n" + conclusion_response.content;
// Create a prompt for a title
std::string title_prompt = "Create a catchy title for this article:\n\n" + article;
auto title_response = co_await context->chat(title_prompt);
// Return the complete article
JsonObject result = {
{"title", title_response.content},
{"introduction", intro_response.content},
{"body", body_response.content},
{"conclusion", conclusion_response.content},
{"full_article", article}
};
Logger::info("Content generation complete!");
co_return result;
}
// Example showing streaming text with coroutines
Task<void> streamText(std::shared_ptr<Context> context, const std::string& prompt) {
Logger::info("Streaming response for prompt: {}", prompt);
// Get a streaming generator
auto generator = context->streamChat(prompt);
std::cout << "Response: ";
// Process each chunk as it arrives
while (auto item = co_await generator.next()) {
std::string chunk = *item;
std::cout << chunk << std::flush;
}
std::cout << std::endl;
Logger::info("Streaming complete!");
co_return;
}
int main(int argc, char* argv[]) {
// Initialize the logger
Logger::init(Logger::Level::INFO);
// Get API key from .env, environment, or command line
std::string api_key;
auto& config = ConfigLoader::getInstance();
// Try to get API key from config or environment
api_key = config.get("GEMINI_API_KEY", "");
// If not found, check command line
if (api_key.empty() && argc > 1) {
api_key = argv[1];
}
// Still not found, show error and exit
if (api_key.empty()) {
Logger::error("API key not found. Please:");
Logger::error("1. Create a .env file with GEMINI_API_KEY=your_key, or");
Logger::error("2. Set the GEMINI_API_KEY environment variable, or");
Logger::error("3. Provide an API key as a command line argument");
return EXIT_FAILURE;
}
// Create LLM
auto llm = createLLM("google", api_key, "gemini-2.0-flash");
// Configure LLM options
LLMOptions options;
options.temperature = 0.7;
options.max_tokens = 2048;
llm->setOptions(options);
// Create agent context
auto context = std::make_shared<Context>();
context->setLLM(llm);
// Register tools
context->registerTool(tools::createWikipediaTool());
context->registerTool(tools::createWebSearchTool(llm));
// Menu-driven example to demonstrate various coroutines
while (true) {
Logger::info("\n========== COROUTINE EXAMPLES ==========");
Logger::info("1. Run autonomous agent with coroutines");
Logger::info("2. Perform research with parallel tool use");
Logger::info("3. Generate content in parallel");
Logger::info("4. Stream text example");
Logger::info("5. Exit");
Logger::info("Enter your choice:");
int choice;
std::cin >> choice;
std::cin.ignore(); // Clear the newline
if (choice >= 5 || choice < 1) {
break;
}
// Get topic from user
std::string topic;
if (choice >= 1 && choice <= 4) {
Logger::info("Enter a topic: ");
std::getline(std::cin, topic);
}
try {
switch (choice) {
case 1: {
// Example 1: Autonomous agent with coroutines
Logger::info("Running autonomous agent with coroutines");
// Create and configure agent
AutonomousAgent agent(context);
agent.setAgentPrompt("You are a helpful assistant that can use tools to perform tasks.");
agent.setPlanningStrategy(AutonomousAgent::PlanningStrategy::REACT);
agent.setStepCallback(stepCallback);
// Configure options
AutonomousAgent::Options agent_options;
agent_options.max_iterations = 3;
agent_options.human_feedback_enabled = true;
agent_options.human_in_the_loop = humanApproval;
agent.setOptions(agent_options);
// Initialize
agent.init();
// Run the agent using coroutines
auto result = blockingWait(agent.run(topic));
// Display result
if (result.contains("answer")) {
Logger::info("\nFinal Answer: {}", result["answer"].get<std::string>());
} else {
Logger::info("\nResult: {}", result.dump(2));
}
break;
}
case 2: {
// Example 2: Research task with parallel tool use
Logger::info("Performing research with coroutines");
auto result = blockingWait(performResearchTask(context, topic));
Logger::info("\nResearch Summary: {}", result["summary"].get<std::string>());
break;
}
case 3: {
// Example 3: Generate content in parallel
Logger::info("Generating content in parallel");
auto result = blockingWait(generateContentInParallel(context, topic));
Logger::info("\nTitle: {}", result["title"].get<std::string>());
Logger::info("\nFull Article:\n{}", result["full_article"].get<std::string>());
break;
}
case 4: {
// Example 4: Stream text
Logger::info("Streaming text example");
blockingWait(streamText(context, "Write a short story about " + topic));
break;
}
default:
Logger::error("Invalid choice");
}
} catch (const std::exception& e) {
Logger::error("Error: {}", e.what());
}
}
return EXIT_SUCCESS;
}