Skip to content

Commit a953d34

Browse files
authored
Always set a parameters schema on a Gemini function declaration, even when it's an empty object (#1998)
1 parent 701ac1b commit a953d34

File tree

6 files changed

+529
-6
lines changed

6 files changed

+529
-6
lines changed

pydantic_ai_slim/pydantic_ai/models/gemini.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -723,9 +723,7 @@ class _GeminiFunction(TypedDict):
723723

724724
def _function_from_abstract_tool(tool: ToolDefinition) -> _GeminiFunction:
725725
json_schema = tool.parameters_json_schema
726-
f = _GeminiFunction(name=tool.name, description=tool.description)
727-
if json_schema.get('properties'):
728-
f['parameters'] = json_schema
726+
f = _GeminiFunction(name=tool.name, description=tool.description, parameters=json_schema)
729727
return f
730728

731729

pydantic_ai_slim/pydantic_ai/models/google.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,9 +469,11 @@ def _process_response_from_parts(
469469

470470
def _function_declaration_from_tool(tool: ToolDefinition) -> FunctionDeclarationDict:
471471
json_schema = tool.parameters_json_schema
472-
f = FunctionDeclarationDict(name=tool.name, description=tool.description)
473-
if json_schema.get('properties'): # pragma: no branch
474-
f['parameters'] = json_schema # type: ignore
472+
f = FunctionDeclarationDict(
473+
name=tool.name,
474+
description=tool.description,
475+
parameters=json_schema, # type: ignore
476+
)
475477
return f
476478

477479

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
interactions:
2+
- request:
3+
headers:
4+
accept:
5+
- '*/*'
6+
accept-encoding:
7+
- gzip, deflate
8+
connection:
9+
- keep-alive
10+
content-length:
11+
- '468'
12+
content-type:
13+
- application/json
14+
host:
15+
- generativelanguage.googleapis.com
16+
method: POST
17+
parsed_body:
18+
contents:
19+
- parts:
20+
- text: run bar for me please
21+
role: user
22+
toolConfig:
23+
function_calling_config:
24+
allowed_function_names:
25+
- bar
26+
- final_result
27+
mode: ANY
28+
tools:
29+
functionDeclarations:
30+
- description: ''
31+
name: bar
32+
parameters:
33+
properties: {}
34+
type: object
35+
- description: The final response which ends this conversation
36+
name: final_result
37+
parameters:
38+
properties:
39+
bar:
40+
type: string
41+
required:
42+
- bar
43+
type: object
44+
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
45+
response:
46+
headers:
47+
alt-svc:
48+
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
49+
content-length:
50+
- '721'
51+
content-type:
52+
- application/json; charset=UTF-8
53+
server-timing:
54+
- gfet4t7; dur=618
55+
transfer-encoding:
56+
- chunked
57+
vary:
58+
- Origin
59+
- X-Origin
60+
- Referer
61+
parsed_body:
62+
candidates:
63+
- avgLogprobs: 2.094004230457358e-05
64+
content:
65+
parts:
66+
- functionCall:
67+
args: {}
68+
name: bar
69+
role: model
70+
finishReason: STOP
71+
modelVersion: gemini-2.0-flash
72+
responseId: t61QaPKoBZSF_NUPqYHxmAg
73+
usageMetadata:
74+
candidatesTokenCount: 1
75+
candidatesTokensDetails:
76+
- modality: TEXT
77+
tokenCount: 1
78+
promptTokenCount: 21
79+
promptTokensDetails:
80+
- modality: TEXT
81+
tokenCount: 21
82+
totalTokenCount: 22
83+
status:
84+
code: 200
85+
message: OK
86+
- request:
87+
headers:
88+
accept:
89+
- '*/*'
90+
accept-encoding:
91+
- gzip, deflate
92+
connection:
93+
- keep-alive
94+
content-length:
95+
- '635'
96+
content-type:
97+
- application/json
98+
host:
99+
- generativelanguage.googleapis.com
100+
method: POST
101+
parsed_body:
102+
contents:
103+
- parts:
104+
- text: run bar for me please
105+
role: user
106+
- parts:
107+
- functionCall:
108+
args: {}
109+
name: bar
110+
role: model
111+
- parts:
112+
- functionResponse:
113+
name: bar
114+
response:
115+
return_value: hello
116+
role: user
117+
toolConfig:
118+
function_calling_config:
119+
allowed_function_names:
120+
- bar
121+
- final_result
122+
mode: ANY
123+
tools:
124+
functionDeclarations:
125+
- description: ''
126+
name: bar
127+
parameters:
128+
properties: {}
129+
type: object
130+
- description: The final response which ends this conversation
131+
name: final_result
132+
parameters:
133+
properties:
134+
bar:
135+
type: string
136+
required:
137+
- bar
138+
type: object
139+
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
140+
response:
141+
headers:
142+
alt-svc:
143+
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
144+
content-length:
145+
- '776'
146+
content-type:
147+
- application/json; charset=UTF-8
148+
server-timing:
149+
- gfet4t7; dur=674
150+
transfer-encoding:
151+
- chunked
152+
vary:
153+
- Origin
154+
- X-Origin
155+
- Referer
156+
parsed_body:
157+
candidates:
158+
- avgLogprobs: -0.002446441538631916
159+
content:
160+
parts:
161+
- functionCall:
162+
args:
163+
bar: hello
164+
name: final_result
165+
role: model
166+
finishReason: STOP
167+
modelVersion: gemini-2.0-flash
168+
responseId: t61QaMaQJ-qm1PIPwJSz4AI
169+
usageMetadata:
170+
candidatesTokenCount: 5
171+
candidatesTokensDetails:
172+
- modality: TEXT
173+
tokenCount: 5
174+
promptTokenCount: 27
175+
promptTokensDetails:
176+
- modality: TEXT
177+
tokenCount: 27
178+
totalTokenCount: 32
179+
status:
180+
code: 200
181+
message: OK
182+
version: 1
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
interactions:
2+
- request:
3+
headers:
4+
accept:
5+
- '*/*'
6+
accept-encoding:
7+
- gzip, deflate
8+
connection:
9+
- keep-alive
10+
content-length:
11+
- '477'
12+
content-type:
13+
- application/json
14+
host:
15+
- generativelanguage.googleapis.com
16+
method: POST
17+
parsed_body:
18+
contents:
19+
- parts:
20+
- text: run bar for me please
21+
role: user
22+
generationConfig: {}
23+
toolConfig:
24+
functionCallingConfig:
25+
mode: ANY
26+
tools:
27+
- functionDeclarations:
28+
- description: ''
29+
name: bar
30+
parameters:
31+
properties: {}
32+
type: OBJECT
33+
- description: The final response which ends this conversation
34+
name: final_result
35+
parameters:
36+
properties:
37+
bar:
38+
type: STRING
39+
required:
40+
- bar
41+
type: OBJECT
42+
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
43+
response:
44+
headers:
45+
alt-svc:
46+
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
47+
content-length:
48+
- '721'
49+
content-type:
50+
- application/json; charset=UTF-8
51+
server-timing:
52+
- gfet4t7; dur=720
53+
transfer-encoding:
54+
- chunked
55+
vary:
56+
- Origin
57+
- X-Origin
58+
- Referer
59+
parsed_body:
60+
candidates:
61+
- avgLogprobs: 2.094004230457358e-05
62+
content:
63+
parts:
64+
- functionCall:
65+
args: {}
66+
name: bar
67+
role: model
68+
finishReason: STOP
69+
modelVersion: gemini-2.0-flash
70+
responseId: Ba1QaMKCL-qm1PIPwJSz4AI
71+
usageMetadata:
72+
candidatesTokenCount: 1
73+
candidatesTokensDetails:
74+
- modality: TEXT
75+
tokenCount: 1
76+
promptTokenCount: 21
77+
promptTokensDetails:
78+
- modality: TEXT
79+
tokenCount: 21
80+
totalTokenCount: 22
81+
status:
82+
code: 200
83+
message: OK
84+
- request:
85+
headers:
86+
accept:
87+
- '*/*'
88+
accept-encoding:
89+
- gzip, deflate
90+
connection:
91+
- keep-alive
92+
content-length:
93+
- '759'
94+
content-type:
95+
- application/json
96+
host:
97+
- generativelanguage.googleapis.com
98+
method: POST
99+
parsed_body:
100+
contents:
101+
- parts:
102+
- text: run bar for me please
103+
role: user
104+
- parts:
105+
- functionCall:
106+
args: {}
107+
id: pyd_ai_4809c3117a3d4ed398851cb98f8ec303
108+
name: bar
109+
role: model
110+
- parts:
111+
- functionResponse:
112+
id: pyd_ai_4809c3117a3d4ed398851cb98f8ec303
113+
name: bar
114+
response:
115+
return_value: hello
116+
role: user
117+
generationConfig: {}
118+
toolConfig:
119+
functionCallingConfig:
120+
mode: ANY
121+
tools:
122+
- functionDeclarations:
123+
- description: ''
124+
name: bar
125+
parameters:
126+
properties: {}
127+
type: OBJECT
128+
- description: The final response which ends this conversation
129+
name: final_result
130+
parameters:
131+
properties:
132+
bar:
133+
type: STRING
134+
required:
135+
- bar
136+
type: OBJECT
137+
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
138+
response:
139+
headers:
140+
alt-svc:
141+
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
142+
content-length:
143+
- '776'
144+
content-type:
145+
- application/json; charset=UTF-8
146+
server-timing:
147+
- gfet4t7; dur=589
148+
transfer-encoding:
149+
- chunked
150+
vary:
151+
- Origin
152+
- X-Origin
153+
- Referer
154+
parsed_body:
155+
candidates:
156+
- avgLogprobs: -0.002446441538631916
157+
content:
158+
parts:
159+
- functionCall:
160+
args:
161+
bar: hello
162+
name: final_result
163+
role: model
164+
finishReason: STOP
165+
modelVersion: gemini-2.0-flash
166+
responseId: Bq1QaNCkF5SF_NUPqYHxmAg
167+
usageMetadata:
168+
candidatesTokenCount: 5
169+
candidatesTokensDetails:
170+
- modality: TEXT
171+
tokenCount: 5
172+
promptTokenCount: 27
173+
promptTokensDetails:
174+
- modality: TEXT
175+
tokenCount: 27
176+
totalTokenCount: 32
177+
status:
178+
code: 200
179+
message: OK
180+
version: 1

0 commit comments

Comments
 (0)