sunholo 0.71.29__py3-none-any.whl → 0.73.2__py3-none-any.whl

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.
@@ -1,326 +0,0 @@
1
- # https://cloud.google.com/vertex-ai/generative-ai/docs/extensions/create-extension
2
- # https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/extension#python
3
- from vertexai.preview import extensions
4
- from .init import init_vertex
5
- from ..logging import log
6
- from ..utils.gcp_project import get_gcp_project
7
- from ..utils.parsers import validate_extension_id
8
-
9
- # https://github.com/GoogleCloudPlatform/applied-ai-engineering-samples/blob/main/genai-on-vertex-ai/vertex_ai_extensions/notebooks/pandas_code_interpreter.ipynb
10
- import base64
11
- import json
12
- import pprint
13
- import pandas
14
- from io import StringIO
15
-
16
- global CODE_INTERPRETER_WRITTEN_FILES
17
- CODE_INTERPRETER_WRITTEN_FILES = []
18
-
19
- def get_extension_import_config(
20
- display_name: str,
21
- description: str,
22
- api_spec_gcs: dict,
23
- service_account_name: dict,
24
- tool_use_examples: list):
25
-
26
- tool_use_examples = [
27
- {
28
- "extensionOperation": {
29
- "operationId": "say_hello",
30
- },
31
- "displayName": "Say hello in the requested language",
32
- "query": "Say hello in French",
33
- "requestParams": {
34
- "fields": [
35
- {
36
- "key": "apiServicePrompt",
37
- "value": {
38
- "string_value": "French",
39
- }
40
- }
41
- ]
42
- },
43
- "responseParams": {
44
- "fields": [
45
- {
46
- "key": "apiServiceOutput",
47
- "value": {
48
- "string_value": "bonjour",
49
- },
50
- }
51
- ],
52
- },
53
- "responseSummary": "Bonjour"
54
- }
55
- ]
56
-
57
-
58
- return {
59
- "displayName": display_name,
60
- "description": description,
61
- "manifest": {
62
- "name": "EXTENSION_NAME_LLM",
63
- "description": "DESCRIPTION_LLM",
64
- "apiSpec": {
65
- "openApiGcsUri": api_spec_gcs,
66
- },
67
- "authConfig": {
68
- "authType": "OAUTH",
69
- "oauthConfig": {"service_account": service_account_name}
70
- }
71
- },
72
- "toolUseExamples": tool_use_examples,
73
- }
74
-
75
- # once an extension is available, call it in code here
76
- def create_extension_instance(
77
- display_name: str,
78
- description: str,
79
- open_api_gcs_uri: str,
80
- llm_name: str=None,
81
- llm_description: str=None,
82
- runtime_config: dict=None,
83
- service_account: str=None,
84
- ):
85
- """
86
- Args:
87
- - display_name: for the human. parsed to be used as extension_name
88
- - description: for the human
89
- - open_api_gcs_uri: location on GCS where open_ai yaml spec is
90
- - llm_name: for the model. If None, uses display_name
91
- - llm_description: for the model. If None, uses description
92
- - service_account: If not specified, the Vertex AI Extension Service Agent is used to execute the extension.
93
-
94
- """
95
- project_id = get_gcp_project()
96
- extension_name = f"projects/{project_id}/locations/us-central1/extensions/{validate_extension_id(display_name)}"
97
-
98
- extension = extensions.Extension.create(
99
- extension_name=extension_name,
100
- display_name=display_name,
101
- description=description,
102
- runtime_config=runtime_config or None,
103
- manifest={
104
- "name": llm_name or display_name,
105
- "description": llm_description or description,
106
- "api_spec": {
107
- "open_api_gcs_uri": open_api_gcs_uri
108
- },
109
- "auth_config": {
110
- "auth_type": "GOOGLE_SERVICE_ACCOUNT_AUTH",
111
- "google_service_account_config": service_account or {},
112
- },
113
- },
114
- )
115
- log.info(f"Created Vertex Extension: {extension_name}")
116
-
117
- return extension
118
-
119
-
120
-
121
- def create_extension_code_interpreter(
122
- code_artifacts_bucket=None
123
- ):
124
-
125
- # only us-central for now
126
- location = "us-central1"
127
- init_vertex(location=location)
128
-
129
- runtime_config=None
130
- if code_artifacts_bucket:
131
- runtime_config = {"codeInterpreterRuntimeConfig":
132
- {
133
- "fileInputGcsBucket": code_artifacts_bucket,
134
- "fileOutputGcsBucket": code_artifacts_bucket
135
- }
136
- }
137
-
138
- llm_description="""
139
- Tool to generate and execute valid Python code from a natural
140
- language description, or to execute custom Python code.
141
- Use this tool to:
142
- - generate and/or execute code for various tasks:
143
- - perform a wide variety of mathematical calculations, for example, add,
144
- subtract, multiply, divide, average, power, factorial, quotient,
145
- formulae, logarithms, random numbers, trigonometric functions, and
146
- equations;
147
- - sort, filter, select top results, and otherwise analyze data (including
148
- data acquired from other tools and Extensions);
149
- - create visualizations, plot charts, draw graphs, shapes, print results,
150
- etc.
151
- - execute custom code and get results and output files.
152
- """
153
-
154
- code_extension = create_extension_instance(
155
- display_name="Code Interpreter",
156
- description="This extension generates and executes code in the specified language",
157
- open_api_gcs_uri="gs://vertex-extension-public/code_interpreter.yaml",
158
- llm_name="code_interpreter_tool",
159
- llm_description=llm_description,
160
- runtime_config=runtime_config
161
- )
162
- log.info(f"Created code extension: {code_extension=}")
163
-
164
- return code_extension
165
-
166
- def execute_extension(operation_id: str,
167
- operation_params: dict,
168
- extension_id: str):
169
-
170
- # only us-central for now
171
- location = "us-central1"
172
- init_vertex(location=location)
173
-
174
- if not extension_id.startswith("projects/"):
175
- project_id=get_gcp_project()
176
- extension_name = f"projects/{project_id}/locations/{location}/extensions/{extension_id}"
177
- else:
178
- extension_name=extension_id
179
-
180
- extension = extensions.Extension(extension_name)
181
-
182
- response = extension.execute(
183
- operation_id=operation_id,
184
- # {"query": "find the max value in the list: [1,2,3,4,-5]"}
185
- operation_params=operation_params,
186
- )
187
-
188
- return response
189
-
190
- def execute_code_extension(query:str, filenames: list[str]=None, gcs_files: list[str]=None):
191
-
192
- if filenames and gcs_files:
193
- raise ValueError("Can't specify both filenames and gcs_files")
194
-
195
- extension_code_interpreter = extensions.Extension.from_hub("code_interpreter")
196
-
197
- file_arr=None
198
- if filenames:
199
- file_arr = [
200
- {
201
- "name": filename,
202
- "contents": base64.b64encode(open(filename, "rb").read()).decode()
203
- }
204
- for filename in filenames
205
- ]
206
-
207
- response = extension_code_interpreter.execute(
208
- operation_id = "generate_and_execute",
209
- operation_params={
210
- "query": query,
211
- "files": file_arr,
212
- "file_gcs_uris": gcs_files
213
- })
214
-
215
- CODE_INTERPRETER_WRITTEN_FILES.extend(
216
- [item['name'] for item in response['output_files']])
217
-
218
- if response.get('execution_error'):
219
- log.error(f"Code Execution Response failed with: {response.get('execution_error')} - maybe retry?")
220
-
221
- return response
222
-
223
- css_styles = """
224
- <style>
225
- .main_summary {
226
- font-weight: bold;
227
- font-size: 14px; color: #4285F4;
228
- background-color:rgba(221, 221, 221, 0.5); padding:8px;}
229
- </style>
230
- """
231
-
232
- # Parser to visualise the content of returned files as HTML.
233
- def parse_files_to_html(outputFiles, save_files_locally = True):
234
- IMAGE_FILE_EXTENSIONS = set(["jpg", "jpeg", "png"])
235
- file_list = []
236
- details_tml = """<details><summary>{name}</summary><div>{html_content}</div></details>"""
237
-
238
- if not outputFiles:
239
- return "No Files generated from the code"
240
- # Sort output_files so images are displayed before other files such as JSON.
241
- for output_file in sorted(
242
- outputFiles,
243
- key=lambda x: x["name"].split(".")[-1] not in IMAGE_FILE_EXTENSIONS,
244
- ):
245
- file_name = output_file.get("name")
246
- file_contents = base64.b64decode(output_file.get("contents"))
247
- if save_files_locally:
248
- open(file_name,"wb").write(file_contents)
249
-
250
- if file_name.split(".")[-1] in IMAGE_FILE_EXTENSIONS:
251
- # Render Image
252
- file_html_content = ('<img src="data:image/png;base64, '
253
- f'{output_file.get("contents")}" />')
254
- elif file_name.endswith(".json"):
255
- # Pretty print JSON
256
- json_pp = pprint.pformat(
257
- json.loads(file_contents.decode()),
258
- compact=False,
259
- width=160)
260
- file_html_content = (f'<span>{json_pp}</span>')
261
- elif file_name.endswith(".csv"):
262
- # CSV
263
- csv_md = pandas.read_csv(
264
- StringIO(file_contents.decode())).to_markdown(index=False)
265
- file_html_content = f'<span>{csv_md}</span>'
266
- elif file_name.endswith(".pkl"):
267
- # PKL
268
- file_html_content = f'<span>Preview N/A</span>'
269
- else:
270
- file_html_content = f"<span>{file_contents.decode()}</span>"
271
-
272
- file_list.append({'name': file_name, "html_content": file_html_content})
273
-
274
- buffer_html = [ details_tml.format(**_file) for _file in file_list ]
275
- return "".join(buffer_html)
276
-
277
- # Processing code interpreter response to html visualization.
278
- def process_response(response: dict, save_files_locally = None) -> None:
279
-
280
- result_template = """
281
- <details open>
282
- <summary class='main_summary'>{summary}:</summary>
283
- <div><pre>{content}</pre></div>
284
- </details>
285
- """
286
-
287
- result = ""
288
- code = response.get('generated_code')
289
- if 'execution_result' in response and response['execution_result']!="":
290
- result = result_template.format(
291
- summary="Executed Code Output",
292
- content=response.get('execution_result'))
293
- else:
294
- result = result_template.format(
295
- summary="Executed Code Output",
296
- content="Code does not produce printable output.")
297
-
298
- if response.get('execution_error', None):
299
- result += result_template.format(
300
- summary="Generated Code Raised a (Possibly Non-Fatal) Exception",
301
- content=response.get('execution_error', None))
302
-
303
- result += result_template.format(
304
- summary="Files Created <u>(Click on filename to view content)</u>",
305
- content=parse_files_to_html(
306
- response.get('output_files', []),
307
- save_files_locally = True))
308
-
309
- html_content = f"""
310
- {css_styles}
311
- <div id='main'>
312
- <div id="right">
313
- <h3>Generated Code by Code Interpreter</h3>
314
- <pre><code>{code}</code></pre>
315
- </div>
316
- <div id="left">
317
- <h3>Code Execution Results</h3>
318
- {result}
319
- </div>
320
- </div>
321
- """
322
- if save_files_locally:
323
- # write to local file
324
- pass
325
-
326
- return html_content