19
19
from __future__ import annotations
20
20
21
21
import json
22
- from typing import Any , List , Literal , Mapping , Tuple
22
+ from typing import Any , List , Literal , Mapping , Tuple , Union
23
23
24
- from bigframes import clients , dtypes , series
25
- from bigframes .core import log_adapter
24
+ import pandas as pd
25
+
26
+ from bigframes import clients , dtypes , series , session
27
+ from bigframes .core import convert , log_adapter
26
28
from bigframes .operations import ai_ops
27
29
30
+ PROMPT_TYPE = Union [
31
+ series .Series ,
32
+ pd .Series ,
33
+ List [Union [str , series .Series , pd .Series ]],
34
+ Tuple [Union [str , series .Series , pd .Series ], ...],
35
+ ]
36
+
28
37
29
38
@log_adapter .method_logger (custom_base_name = "bigquery_ai" )
30
39
def generate_bool (
31
- prompt : series . Series | List [ str | series . Series ] | Tuple [ str | series . Series , ...] ,
40
+ prompt : PROMPT_TYPE ,
32
41
* ,
33
42
connection_id : str | None = None ,
34
43
endpoint : str | None = None ,
@@ -51,7 +60,7 @@ def generate_bool(
51
60
0 {'result': True, 'full_response': '{"candidate...
52
61
1 {'result': True, 'full_response': '{"candidate...
53
62
2 {'result': False, 'full_response': '{"candidat...
54
- dtype: struct<result: bool, full_response: string , status: string>[pyarrow]
63
+ dtype: struct<result: bool, full_response: extension<dbjson<JSONArrowType>> , status: string>[pyarrow]
55
64
56
65
>>> bbq.ai.generate_bool((df["col_1"], " is a ", df["col_2"])).struct.field("result")
57
66
0 True
@@ -60,8 +69,9 @@ def generate_bool(
60
69
Name: result, dtype: boolean
61
70
62
71
Args:
63
- prompt (series.Series | List[str|series.Series] | Tuple[str|series.Series, ...]):
64
- A mixture of Series and string literals that specifies the prompt to send to the model.
72
+ prompt (Series | List[str|Series] | Tuple[str|Series, ...]):
73
+ A mixture of Series and string literals that specifies the prompt to send to the model. The Series can be BigFrames Series
74
+ or pandas Series.
65
75
connection_id (str, optional):
66
76
Specifies the connection to use to communicate with the model. For example, `myproject.us.myconnection`.
67
77
If not provided, the connection from the current session will be used.
@@ -84,7 +94,7 @@ def generate_bool(
84
94
Returns:
85
95
bigframes.series.Series: A new struct Series with the result data. The struct contains these fields:
86
96
* "result": a BOOL value containing the model's response to the prompt. The result is None if the request fails or is filtered by responsible AI.
87
- * "full_response": a STRING value containing the JSON response from the projects.locations.endpoints.generateContent call to the model.
97
+ * "full_response": a JSON value containing the response from the projects.locations.endpoints.generateContent call to the model.
88
98
The generated text is in the text element.
89
99
* "status": a STRING value that contains the API response status for the corresponding row. This value is empty if the operation was successful.
90
100
"""
@@ -104,7 +114,7 @@ def generate_bool(
104
114
105
115
106
116
def _separate_context_and_series (
107
- prompt : series . Series | List [ str | series . Series ] | Tuple [ str | series . Series , ...] ,
117
+ prompt : PROMPT_TYPE ,
108
118
) -> Tuple [List [str | None ], List [series .Series ]]:
109
119
"""
110
120
Returns the two values. The first value is the prompt with all series replaced by None. The second value is all the series
@@ -123,18 +133,19 @@ def _separate_context_and_series(
123
133
return [None ], [prompt ]
124
134
125
135
prompt_context : List [str | None ] = []
126
- series_list : List [series .Series ] = []
136
+ series_list : List [series .Series | pd . Series ] = []
127
137
138
+ session = None
128
139
for item in prompt :
129
140
if isinstance (item , str ):
130
141
prompt_context .append (item )
131
142
132
- elif isinstance (item , series .Series ):
143
+ elif isinstance (item , ( series .Series , pd . Series ) ):
133
144
prompt_context .append (None )
134
145
135
- if item . dtype == dtypes . OBJ_REF_DTYPE :
136
- # Multi-model support
137
- item = item .blob . read_url ()
146
+ if isinstance ( item , series . Series ) and session is None :
147
+ # Use the first available BF session if there's any.
148
+ session = item ._session
138
149
series_list .append (item )
139
150
140
151
else :
@@ -143,7 +154,20 @@ def _separate_context_and_series(
143
154
if not series_list :
144
155
raise ValueError ("Please provide at least one Series in the prompt" )
145
156
146
- return prompt_context , series_list
157
+ converted_list = [_convert_series (s , session ) for s in series_list ]
158
+
159
+ return prompt_context , converted_list
160
+
161
+
162
+ def _convert_series (
163
+ s : series .Series | pd .Series , session : session .Session | None
164
+ ) -> series .Series :
165
+ result = convert .to_bf_series (s , default_index = None , session = session )
166
+
167
+ if result .dtype == dtypes .OBJ_REF_DTYPE :
168
+ # Support multimodel
169
+ return result .blob .read_url ()
170
+ return result
147
171
148
172
149
173
def _resolve_connection_id (series : series .Series , connection_id : str | None ):
0 commit comments