gemini-agent-framework 0.1.1__tar.gz → 0.1.2__tar.gz

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.
@@ -2,4 +2,4 @@ __pycache__
2
2
  llama.log
3
3
  localllm.exe
4
4
  .env
5
- llm_test
5
+ llm_test
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-agent-framework
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A framework for building agents that use Gemini's function calling capabilities
5
5
  Project-URL: Homepage, https://github.com/m7mdony/gemini-agent-framework
6
6
  Project-URL: Documentation, https://github.com/m7mdony/gemini-agent-framework#readme
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "gemini-agent-framework"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "A framework for building agents that use Gemini's function calling capabilities"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -0,0 +1,4 @@
1
+ from .agent import Agent
2
+
3
+ __version__ = "0.1.2"
4
+ __all__ = ["Agent"]
@@ -31,6 +31,7 @@ class Agent:
31
31
  Agent._tools_registry[func.__name__]['description'] = desc
32
32
  Agent._tools_registry[func.__name__]['signature'] = inspect.signature(func)
33
33
  Agent._tools_registry[func.__name__]['function_ref'] = func
34
+ Agent._tools_registry[func.__name__]['is_method'] = inspect.ismethod(func)
34
35
  @wraps(func)
35
36
  def wrapper(*args, **kwargs):
36
37
  return func(*args, **kwargs)
@@ -48,6 +49,7 @@ class Agent:
48
49
  Agent._tools_registry[func.__name__]['signature'] = inspect.signature(func)
49
50
  if 'function_ref' not in Agent._tools_registry[func.__name__]:
50
51
  Agent._tools_registry[func.__name__]['function_ref'] = func
52
+ Agent._tools_registry[func.__name__]['is_method'] = inspect.ismethod(func)
51
53
  @wraps(func)
52
54
  def wrapper(*args, **kwargs):
53
55
  return func(*args, **kwargs)
@@ -60,7 +62,7 @@ class Agent:
60
62
 
61
63
  Args:
62
64
  api_key: Your Google Generative AI API key.
63
- tools: A list of Python functions decorated as tools.
65
+ tools: A list of Python functions or class methods decorated as tools.
64
66
  model_name: The name of the Gemini model to use.
65
67
  """
66
68
  if not api_key:
@@ -72,6 +74,7 @@ class Agent:
72
74
 
73
75
  self._registered_tools_json: List[Dict[str, Any]] = [] # Store JSON representation
74
76
  self._tool_functions: Dict[str, Callable] = {} # Map name to actual function
77
+ self._tool_instances: Dict[str, Any] = {} # Store instances for class methods
75
78
  self._intermediate_results: Dict[str, Any] = {} # Store intermediate results
76
79
 
77
80
  if tools:
@@ -90,6 +93,12 @@ class Agent:
90
93
  print(f"Warning: Function '{tool_name}' is missing @Agent.description. Skipping.")
91
94
  continue
92
95
 
96
+ # Store the bound method directly if it's a class method
97
+ if inspect.ismethod(func):
98
+ self._tool_functions[tool_name] = func
99
+ else:
100
+ self._tool_functions[tool_name] = metadata['function_ref']
101
+
93
102
  # Build the parameters schema JSON
94
103
  gemini_params_schema = {
95
104
  "type": "OBJECT",
@@ -102,6 +111,9 @@ class Agent:
102
111
  if not params_def and signature:
103
112
  params_def = {}
104
113
  for name, param in signature.parameters.items():
114
+ # Skip 'self' parameter for class methods
115
+ if name == 'self' and inspect.ismethod(func):
116
+ continue
105
117
  py_type = param.annotation if param.annotation != inspect.Parameter.empty else str
106
118
  params_def[name] = {'type': py_type, 'description': f'Parameter {name}'}
107
119
 
@@ -125,7 +137,6 @@ class Agent:
125
137
  del declaration_json["parameters"]
126
138
 
127
139
  self._registered_tools_json.append(declaration_json)
128
- self._tool_functions[tool_name] = metadata['function_ref']
129
140
 
130
141
  def _get_system_prompt(self) -> str:
131
142
  """Returns a system prompt that guides the model in breaking down complex operations."""
@@ -192,9 +203,9 @@ class Agent:
192
203
  self._intermediate_results = {}
193
204
 
194
205
  if not system_prompt:
195
- system_prompt = self._get_system_prompt() + system_prompt
196
- else:
197
206
  system_prompt = self._get_system_prompt()
207
+ else:
208
+ system_prompt = self._get_system_prompt() + system_prompt
198
209
 
199
210
  current_contents = conversation_history if conversation_history else []
200
211
  if system_prompt and not current_contents:
@@ -214,6 +225,14 @@ class Agent:
214
225
 
215
226
  if response_structure and not self._registered_tools_json:
216
227
  apply_structure_later = False
228
+ # If response_structure is a string type, make it more flexible
229
+ if response_structure.get("type") == "string":
230
+ response_structure = {
231
+ "type": ["string", "object"],
232
+ "properties": {
233
+ "value": {"type": "string"}
234
+ }
235
+ }
217
236
  payload["generationConfig"] = {
218
237
  "response_mime_type": "application/json",
219
238
  "response_schema": response_structure
@@ -272,7 +291,9 @@ class Agent:
272
291
  if result_key in self._intermediate_results:
273
292
  args[key] = self._intermediate_results[result_key]
274
293
 
294
+ # Call the function directly - it's already bound if it's a method
275
295
  function_result = tool_function(**args)
296
+
276
297
  print(f"--- Function Result: {function_result} ---")
277
298
 
278
299
  result_key = f"result_{len(self._intermediate_results)}"
@@ -0,0 +1,66 @@
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from gemini_agent import Agent
4
+
5
+ load_dotenv()
6
+
7
+ def test_basic_operations():
8
+ # Define some basic math operations
9
+ @Agent.description("Multiplies two numbers.")
10
+ @Agent.parameters({
11
+ 'a': {'type': int, 'description': 'The first number'},
12
+ 'b': {'type': int, 'description': 'The second number'}
13
+ })
14
+ def multiply(a: int, b: int) -> int:
15
+ return a * b
16
+
17
+ @Agent.description("Adds two numbers.")
18
+ @Agent.parameters({
19
+ 'a': {'type': int, 'description': 'The first number'},
20
+ 'b': {'type': int, 'description': 'The second number'}
21
+ })
22
+ def add(a: int, b: int) -> int:
23
+ return a + b
24
+
25
+ # Create an agent with the math tools
26
+ agent = Agent(
27
+ api_key=os.getenv("GEMINI_API_KEY"),
28
+ tools=[multiply, add]
29
+ )
30
+
31
+ # Test a simple multiplication
32
+ response = agent.prompt("Multiply 3 and 7")
33
+ print(f"Multiplication result: {response}") # Should be 21
34
+
35
+ # Use the agent
36
+ response = agent.prompt(user_prompt="multiply 3 and 7 then add 5 to the result" ,
37
+ system_prompt="You are a helpful assistant give your response always with ❤️ at the start of the line. in your response you should mention the function you used." ,
38
+ response_structure=
39
+ {
40
+ "type": "object",
41
+ "properties": {
42
+ "used_functions": {
43
+ "type": "array",
44
+ "items": {
45
+ "type": "object",
46
+ "properties": {
47
+ "function_name": {"type": "string"},
48
+ "parameters": {
49
+ "type": "object",
50
+ "properties": {
51
+ "a": {"type": "integer"},
52
+ "b": {"type": "integer"}
53
+ }
54
+ }
55
+ }
56
+ }
57
+ },
58
+ "answer": {"type": "string"}
59
+
60
+ }
61
+ }
62
+ )
63
+ print(response) # Should output 21
64
+
65
+ if __name__ == "__main__":
66
+ test_basic_operations()
@@ -0,0 +1,67 @@
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from gemini_agent import Agent
4
+
5
+ load_dotenv()
6
+
7
+ class Calculator:
8
+ def __init__(self):
9
+ self.memory = 0
10
+
11
+ @Agent.description("Multiplies a number by the stored memory value.")
12
+ @Agent.parameters({
13
+ 'number': {'type': int, 'description': 'The number to multiply with memory'}
14
+ })
15
+ def multiply_with_memory(self, number: int) -> int:
16
+ result = self.memory * number
17
+ self.memory = result
18
+ return result
19
+
20
+ @Agent.description("Adds a number to the stored memory value.")
21
+ @Agent.parameters({
22
+ 'number': {'type': int, 'description': 'The number to add to memory'}
23
+ })
24
+ def add_to_memory(self, number: int) -> int:
25
+ result = self.memory + number
26
+ self.memory = result
27
+ return result
28
+
29
+ def test_class_methods():
30
+ # Create a calculator instance
31
+ calculator = Calculator()
32
+
33
+ # Create an agent with the calculator methods
34
+ agent = Agent(
35
+ api_key=os.getenv("GEMINI_API_KEY"),
36
+ tools=[calculator.multiply_with_memory, calculator.add_to_memory]
37
+ )
38
+
39
+ # Test using class methods
40
+ response = agent.prompt(
41
+ "Multiply 5 with memory (starting at 0), then add 10 to the result",
42
+ response_structure={
43
+ "type": "object",
44
+ "properties": {
45
+ "used_functions": {
46
+ "type": "array",
47
+ "items": {
48
+ "type": "object",
49
+ "properties": {
50
+ "function_name": {"type": "string"},
51
+ "parameters": {
52
+ "type": "object",
53
+ "properties": {
54
+ "number": {"type": "integer"}
55
+ }
56
+ }
57
+ }
58
+ }
59
+ },
60
+ "answer": {"type": "string"}
61
+ }
62
+ }
63
+ )
64
+ print(response)
65
+
66
+ if __name__ == "__main__":
67
+ test_class_methods()
@@ -1,4 +0,0 @@
1
- from .agent import Agent
2
-
3
- __version__ = "0.1.1"
4
- __all__ = ["Agent"]
@@ -1,48 +0,0 @@
1
- import os
2
- from dotenv import load_dotenv
3
- from src.gemini_agent import Agent
4
-
5
- load_dotenv()
6
-
7
- def test_basic_operations():
8
- # Define some basic math operations
9
- @Agent.description("Multiplies two numbers.")
10
- @Agent.parameters({
11
- 'a': {'type': int, 'description': 'The first number'},
12
- 'b': {'type': int, 'description': 'The second number'}
13
- })
14
- def multiply(a: int, b: int) -> int:
15
- return a * b
16
-
17
- @Agent.description("Adds two numbers.")
18
- @Agent.parameters({
19
- 'a': {'type': int, 'description': 'The first number'},
20
- 'b': {'type': int, 'description': 'The second number'}
21
- })
22
- def add(a: int, b: int) -> int:
23
- return a + b
24
-
25
- # Create an agent with the math tools
26
- agent = Agent(
27
- api_key=os.getenv("GEMINI_API_KEY"),
28
- tools=[multiply, add]
29
- )
30
-
31
- # Test a simple multiplication
32
- response = agent.prompt("Multiply 3 and 7")
33
- print(f"Multiplication result: {response}") # Should be 21
34
-
35
- # Test a complex operation
36
- response = agent.prompt(
37
- "Multiply 3 and 7, then add 4 to the result",
38
- response_structure={
39
- "type": "object",
40
- "properties": {
41
- "result": {"type": "number"}
42
- }
43
- }
44
- )
45
- print(f"Complex operation result: {response}") # Should be {"result": 25}
46
-
47
- if __name__ == "__main__":
48
- test_basic_operations()