Skip to content

Commit 9cc4ecd

Browse files
committed
Modified Agents and connected it with endpoints
1 parent 4428a3f commit 9cc4ecd

File tree

5 files changed

+262
-47
lines changed

5 files changed

+262
-47
lines changed
Lines changed: 65 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
from google.adk.agents import Agent, LoopAgent
22

3-
summarizer_agent = Agent(
4-
name="Summarizer_Agent",
3+
quizzes_agent = Agent(
4+
name="Quizzes_Agent",
55
model="gemini-2.0-flash",
66
description=(
7-
"You are a Summarizer Agent operating under the control of a Manager Agent in a multi-agent system. Your sole purpose is to generate concise, accurate, and coherent summaries from the content provided to you."
7+
"This is an AI agent which is responsible for generating MCQ questions and answers from the content provided to it."
88
),
99
instruction=(
10-
"You are the Summarizer Agent responsible for generating accurate, concise summaries of the content provided to you by the Manager Agent. Also you are to return this output back to the manager agent."
10+
"You are the Quizzes Agent responsible for generating MCQ questions with 4 options and answers of the content provided to you by the Manager Agent. Also you are to return this output back to the manager agent."
11+
)
12+
)
13+
14+
summarizer_agent = Agent(
15+
name="summarizer_agent",
16+
model="gemini-2.0-flash-exp",
17+
description=(
18+
"This is an AI agent which is responsible for generating summaries of the content provided to it."
19+
),
20+
instruction=(
21+
"""You are a Summarizer Agent in an educational multi-agent system.
22+
23+
Your role:
24+
- Create concise, accurate summaries of educational content
25+
- Focus on key concepts, main ideas, and important details
26+
- Maintain academic accuracy and clarity
27+
- Structure summaries logically with clear headings when appropriate
28+
29+
When given content, analyze it thoroughly and provide a well-structured summary that captures the essential information in a clear, academic style."""
1130
)
1231
)
1332

@@ -18,20 +37,20 @@
1837
"This is an AI agent which is responsible for extracting relevant references or citations from the content provided to it."
1938
),
2039
instruction=(
21-
"""You are a Reference Extraction Agent working under a Manager Agent in a multi-agent system.
22-
Your primary responsibility is to carefully scan the provided content and extract all relevant references or citations strictly from this content. These may include:
40+
"""You are a Reference Extraction Agent specialized in identifying and extracting citations, references, and source materials from educational content.
2341
24-
- Document titles
25-
- Section or subsection headings/numbers
26-
- In-text citations
27-
- Footnotes
28-
- Bibliographic references
29-
- URLs or document links
30-
- Mentioned papers, books, articles, datasets, standards, or guidelines
31-
- Any internal or external reference points stated in the content
32-
33-
34-
Also you are to return this output back to the manager agent."""
42+
Your role:
43+
- Scan content for all types of references including:
44+
* Academic citations (APA, MLA, Chicago, etc.)
45+
* URLs and web links
46+
* Book titles and authors
47+
* Journal articles and papers
48+
* Document titles and section references
49+
* Footnotes and endnotes
50+
- Format extracted references clearly and organized
51+
- Include page numbers, dates, and other citation details when available
52+
53+
Provide a comprehensive list of all references related to the content provided to you. Make sure that you include at least 5 references."""
3554
)
3655
)
3756

@@ -42,27 +61,15 @@
4261
"This is an AI agent which is responsible for generating flash cards from the content provided to it."
4362
),
4463
instruction=(
45-
"""You are a Flashcard Generation Agent working under the Manager Agent in a multi-agent system.
46-
Your primary responsibility is to generate a list of question-answer flashcards designed to aid in the quick revision of the concepts, facts, and ideas present in the provided content.
47-
48-
These flashcards are intended to cover all critical points, definitions, formulas, principles, processes, or factual data contained within the content.
49-
You must not use any outside knowledge, assumptions, or inference beyond what is present in the provided material.
64+
"""You are a Flashcard Generation Agent that creates effective study flashcards from educational content.
5065
51-
You are to return the flashcards in a json format with the following structure:
52-
{
53-
"flashcards": [
54-
{
55-
"question": "Question 1",
56-
"answer": "Answer 1"
57-
},
58-
{
59-
"question": "Question 2",
60-
"answer": "Answer 2"
61-
}
62-
]
63-
}
66+
Your role:
67+
- Analyze content to identify key facts, concepts, and definitions
68+
- Create clear question-answer pairs that test understanding
69+
- Ensure questions are specific and answers are concise but complete
70+
- Cover all important topics from the provided content
6471
65-
Also you are to return this output back to the manager agent."""
72+
Create comprehensive flashcards that facilitate active recall and help students understand key concepts."""
6673
)
6774
)
6875

@@ -73,13 +80,28 @@
7380
"This AI agent functions as an orchestrator and coordinator in a multi-agent system designed to answer queries based on domain-specific content provided to it. Its primary role is to manage the interactions between multiple specialized agents and ensure accurate, context-aware, and efficient responses to user queries."
7481
),
7582
instruction=(
76-
"You are the Manager Agent responsible for managing and directing a set of specialized AI sub-agents. Your purpose is to answer user queries solely based on the content provided to you, ensuring accuracy, relevance, and clarity. You are also responsible for giving the output to the user in whatever structure it desires be it json or pdf or any other format."
83+
"""You are the Manager Agent for the EduAssistant multi-agent system.
84+
85+
Your role:
86+
- Understand user requests and determine appropriate actions
87+
- Coordinate with specialized agents when needed:
88+
* Use summarizer_agent for summarization requests
89+
* Use reference_agent for reference extraction requests
90+
* Use flashcard_agent for flashcard generation requests
91+
* Use quizzes_agent for quizzes generation requests
92+
- Provide comprehensive educational assistance
93+
- Maintain academic accuracy and helpful tone
94+
- Format responses appropriately based on user needs
95+
96+
Available agents:
97+
- summarizer_agent: Creates summaries of educational content
98+
- reference_agent: Extracts references and citations
99+
- flashcard_agent: Generates study flashcards
100+
- quizzes_agent: Generates quizzes from educational content
101+
102+
When users ask for specific functions, delegate to the appropriate agent and provide the results in a clear, helpful format asked by the user."""
77103
),
78-
sub_agents=[summarizer_agent, reference_agent, flash_card_agent],
104+
sub_agents=[quizzes_agent, reference_agent, flash_card_agent, summarizer_agent],
79105
)
80106

81-
root_agent = LoopAgent(
82-
name="Loop_Agent",
83-
max_iterations=5,
84-
sub_agents=[manager_agent],
85-
)
107+
root_agent = manager_agent
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export async function extractJsonFromResponse(response: string): Promise<any> {
2+
const match = response.match(/```json\s*([\s\S]*?)\s*```/);
3+
if (match && match[1]) {
4+
try {
5+
return JSON.parse(match[1]);
6+
} catch (e) {
7+
console.error('Failed to parse JSON from response:', e);
8+
return null;
9+
}
10+
}
11+
return null;
12+
}

frontend/src/ai/flows/generate-flashcards.ts

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@
88
* - GenerateFlashcardsOutput - The return type for the generateFlashcards function.
99
*/
1010

11-
import {ai} from '@/ai/genkit';
11+
import {genkit} from 'genkit';
12+
import {googleAI} from '@genkit-ai/googleai';
1213
import {z} from 'genkit';
14+
import { extractJsonFromResponse } from './flow_utils';
15+
16+
const ai = genkit({
17+
plugins: [googleAI()],
18+
model: 'googleai/gemini-2.0-flash',
19+
});
1320

1421
const GenerateFlashcardsInputSchema = z.object({
1522
courseMaterial: z
@@ -26,7 +33,66 @@ const GenerateFlashcardsOutputSchema = z.object({
2633
export type GenerateFlashcardsOutput = z.infer<typeof GenerateFlashcardsOutputSchema>;
2734

2835
export async function generateFlashcards(input: GenerateFlashcardsInput): Promise<GenerateFlashcardsOutput> {
29-
return generateFlashcardsFlow(input);
36+
37+
// Use ADK /run endpoint with configurable backend URL
38+
const ADK_URL = process.env.NEXT_PUBLIC_AGENT_API_URL || "http://localhost:8000";
39+
try {
40+
const res = await fetch(`${ADK_URL}/run`, {
41+
method: "POST",
42+
headers: { "Content-Type": "application/json" },
43+
body: JSON.stringify({
44+
input: `Create flashcards for this content: ${input.courseMaterial}`,
45+
metadata: {
46+
request_type: "flashcards",
47+
course_material: input.courseMaterial,
48+
output_schema: {
49+
type: "object",
50+
properties: {
51+
flashcards: {
52+
type: "array",
53+
items: {
54+
type: "object",
55+
properties: {
56+
front: { type: "string" },
57+
back: { type: "string" }
58+
},
59+
required: ["front", "back"]
60+
}
61+
}
62+
},
63+
required: ["flashcards"]
64+
}
65+
}
66+
})
67+
});
68+
if (!res.ok) throw new Error(`Failed to generate flashcards from backend agent: ${res.status}`);
69+
const data = await extractJsonFromResponse(await res.text());
70+
71+
// ADK returns response in data.output
72+
let result;
73+
try {
74+
result = typeof data === 'string' ? JSON.parse(data) : data;
75+
} catch {
76+
result = data;
77+
}
78+
// Ensure the response matches our expected schema
79+
if (result.flashcards && Array.isArray(result.flashcards)) {
80+
return result;
81+
} else if (Array.isArray(result)) {
82+
return { flashcards: result };
83+
} else {
84+
throw new Error('Invalid flashcards format received from agent');
85+
}
86+
} catch (error) {
87+
console.error('Flashcard generation error:', error);
88+
// Fallback to local Genkit flow if ADK fails
89+
try {
90+
return await generateFlashcardsFlow(input);
91+
} catch (fallbackError) {
92+
console.error("Error in fallback implementation:", fallbackError);
93+
throw fallbackError;
94+
}
95+
}
3096
}
3197

3298
const prompt = ai.definePrompt({

frontend/src/ai/flows/generate-quizzes.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import {ai} from '@/ai/genkit';
1313
import {z} from 'genkit';
14+
import { extractJsonFromResponse } from './flow_utils';
1415

1516
const GenerateQuizzesInputSchema = z.object({
1617
courseMaterial: z
@@ -37,7 +38,68 @@ export type GenerateQuizzesOutput = z.infer<typeof GenerateQuizzesOutputSchema>;
3738
export async function generateQuizzes(
3839
input: GenerateQuizzesInput
3940
): Promise<GenerateQuizzesOutput> {
40-
return generateQuizzesFlow(input);
41+
// Use ADK /run endpoint with configurable backend URL
42+
const ADK_URL = process.env.NEXT_PUBLIC_AGENT_API_URL || "http://localhost:8000";
43+
try {
44+
const res = await fetch(`${ADK_URL}/run`, {
45+
method: "POST",
46+
headers: { "Content-Type": "application/json" },
47+
body: JSON.stringify({
48+
input: `Generate ${input.numQuestions} quiz questions based on this content: ${input.courseMaterial}`,
49+
metadata: {
50+
request_type: "quizzes",
51+
course_material: input.courseMaterial,
52+
output_schema: {
53+
type: "object",
54+
properties: {
55+
quiz: {
56+
type: "array",
57+
items: {
58+
type: "object",
59+
properties: {
60+
question: { type: "string" },
61+
options: {
62+
type: "array",
63+
items: { type: "string" }
64+
},
65+
correctAnswer: { type: "string" }
66+
},
67+
required: ["question", "options", "correctAnswer"]
68+
}
69+
}
70+
},
71+
required: ["quiz"]
72+
}
73+
}
74+
})
75+
});
76+
77+
if (!res.ok) {
78+
throw new Error(`Failed to generate quizzes: ${res.statusText}`);
79+
}
80+
81+
const data = await extractJsonFromResponse(await res.text());
82+
let result;
83+
try {
84+
result = typeof data === 'string' ? JSON.parse(data) : data;
85+
} catch {
86+
result = data;
87+
}
88+
// Ensure the response matches our expected schema
89+
if (!GenerateQuizzesOutputSchema.safeParse(result).success) {
90+
throw new Error("Failed to parse response as GenerateQuizzesOutput");
91+
}
92+
return result;
93+
} catch (error) {
94+
console.error("Error generating quizzes:", error);
95+
try {
96+
// Fall back to the local implementation if the API call fails
97+
return await generateQuizzesFlow(input);
98+
} catch (fallbackError) {
99+
console.error("Error in fallback implementation:", fallbackError);
100+
throw fallbackError;
101+
}
102+
}
41103
}
42104

43105
const prompt = ai.definePrompt({

frontend/src/ai/flows/suggest-resources.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import {ai} from '@/ai/genkit';
1212
import {z} from 'genkit';
13+
import { extractJsonFromResponse } from './flow_utils';
1314

1415
const SuggestResourcesInputSchema = z.object({
1516
courseContent: z
@@ -28,7 +29,59 @@ const SuggestResourcesOutputSchema = z.array(SuggestedResourceSchema).describe('
2829
export type SuggestResourcesOutput = z.infer<typeof SuggestResourcesOutputSchema>;
2930

3031
export async function suggestResources(input: SuggestResourcesInput): Promise<SuggestResourcesOutput> {
31-
return suggestResourcesFlow(input);
32+
// Use ADK /run endpoint with configurable backend URL
33+
const ADK_URL = process.env.NEXT_PUBLIC_AGENT_API_URL || "http://localhost:8000";
34+
try {
35+
const res = await fetch(`${ADK_URL}/run`, {
36+
method: "POST",
37+
headers: { "Content-Type": "application/json" },
38+
body: JSON.stringify({
39+
input: `Take this content and give me reference links for this content: ${input.courseContent}`,
40+
metadata: {
41+
request_type: "suggest_resources",
42+
course_content: input.courseContent,
43+
output_schema: {
44+
type: "array",
45+
items: {
46+
type: "object",
47+
properties: {
48+
title: { type: "string" },
49+
url: { type: "string", format: "uri" },
50+
reason: { type: "string" }
51+
},
52+
required: ["title", "url", "reason"]
53+
}
54+
}
55+
}
56+
})
57+
});
58+
59+
if (!res.ok) {
60+
throw new Error(`Failed to suggest resources: ${res.statusText}`);
61+
}
62+
63+
const data = extractJsonFromResponse(await res.text());
64+
let result;
65+
try {
66+
result = typeof data === 'string' ? JSON.parse(data) : data;
67+
} catch {
68+
result = data;
69+
}
70+
// Ensure the response matches our expected schema
71+
if (!SuggestResourcesOutputSchema.safeParse(result).success) {
72+
throw new Error("Failed to parse response as SuggestResourcesOutput");
73+
}
74+
return result;
75+
} catch (error) {
76+
console.error("Error in API call, falling back to local flow:", error);
77+
try {
78+
// Fall back to the local implementation if the API call fails
79+
return await suggestResourcesFlow(input);
80+
} catch (fallbackError) {
81+
console.error("Error in fallback implementation:", fallbackError);
82+
throw fallbackError;
83+
}
84+
}
3285
}
3386

3487
const resourceSuggestionTool = ai.defineTool({

0 commit comments

Comments
 (0)