-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgemini_tool_formater_example.py
159 lines (137 loc) · 5.77 KB
/
gemini_tool_formater_example.py
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
# tool_converter_example.py
import inspect
import json
from typing import List, Callable, Dict
import google.generativeai as genai
from concurrent.futures import ThreadPoolExecutor
import os
class ToolConverter:
def __init__(self, indent_size: int = 4):
self.indent_size = indent_size
genai.configure(api_key=os.environ.get("GEMINI_API_KEY", ""))
self.model = genai.GenerativeModel("gemini-1.5-flash-latest")
def _get_function_source(self, func: Callable) -> str:
"""Gets the complete source code of a function, including docstring."""
source = inspect.getsource(func)
# Remove any extra indentation from the source
lines = source.split('\n')
if lines:
# Find the indentation of the first line
first_line_indent = len(lines[0]) - len(lines[0].lstrip())
# Remove that indentation from all lines
lines = [line[first_line_indent:] if line.startswith(' ' * first_line_indent) else line
for line in lines]
return '\n'.join(lines)
def convert_functions_to_string(self, functions: List[Callable]) -> List[str]:
"""
Converts a list of Python functions into a list of strings, each containing a complete function definition.
:param functions: List of Python functions
:return: List of strings, each containing a function definition
"""
function_strings = []
for func in functions:
function_strings.append(self._get_function_source(func))
return function_strings
def create_function_schema(self, function_string: str) -> Dict:
"""
Creates a function schema from a string containing a function definition using Gemini.
"""
prompt = f"""Generate a JSON schema for the following Python function. The schema should follow this format:
{{
"type": "function",
"function": {{
"name": "function_name",
"description": "function description",
"strict": true,
"parameters": {{
"type": "object",
"properties": {{
// parameter definitions
}},
"required": ["param1", "param2", ...],
"additionalProperties": false
}}
}}
}}
Function to convert:
{function_string}
"""
response = self.model.generate_content(
prompt,
generation_config=genai.GenerationConfig(
temperature=0.2,
top_p=0.95,
top_k=40,
max_output_tokens=8192,
response_mime_type="application/json"
)
)
# Extract the JSON from the response
try:
return json.loads(response.text)
except json.JSONDecodeError:
# If the response isn't valid JSON, try to extract it from the text
text = response.text
start = text.find('{')
end = text.rfind('}') + 1
if start >= 0 and end > start:
try:
return json.loads(text[start:end])
except json.JSONDecodeError:
return {"error": "Failed to parse Gemini response"}
return {"error": "Failed to parse Gemini response"}
def create_function_schemas(self, function_strings: List[str], max_workers: int = None) -> str:
"""
Creates function schemas for multiple functions in parallel using ThreadPool
and combines them into a single JSON string.
:param function_strings: List of function definition strings
:param max_workers: Maximum number of worker threads (defaults to None, which lets ThreadPoolExecutor decide)
:return: Combined JSON string containing all function schemas
"""
with ThreadPoolExecutor(max_workers=max_workers) as executor:
# Map each function string to create_function_schema
schema_futures = executor.map(self.create_function_schema, function_strings)
# Collect all schemas
schemas = []
for schema in schema_futures:
if "error" not in schema:
schemas.append(schema)
# Combine all schemas into a single JSON string
combined_schema = json.dumps(schemas, indent=2)
return combined_schema
def generate_schemas(self, functions: List[Callable]) -> dict:
"""
Generates Gemini function schemas.
Args:
functions: List of Python functions to convert
Returns:
dict: Dictionary containing Gemini schema
{
"gemini": [...]
}
"""
# Convert functions to strings
function_strings = self.convert_functions_to_string(functions)
# Generate Gemini schema
gemini_schema = self.create_function_schemas(function_strings)
gemini_parsed = json.loads(gemini_schema)
# Return Gemini schema
return {
"gemini": gemini_parsed
}
# Example usage
def print_text(text: str) -> str:
"""Prints any text sent to the function and returns confirmation"""
print(text)
return "Text is printed"
def add_numbers(a: float, b: float) -> float:
"""Adds two numbers together"""
return a + b
if __name__ == "__main__":
# Create converter and generate schema
converter = ToolConverter()
functions = [print_text, add_numbers]
schemas = converter.generate_schemas(functions)
# Print Gemini schema
print("Gemini Schema:")
print(json.dumps(schemas["gemini"], indent=2))