dhisana 0.0.1__py3-none-any.whl → 0.0.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.
- dhisana/utils/agent_tools.py +1 -329
- dhisana/utils/openai_helpers.py +21 -9
- dhisana/utils/tools_json.py +0 -352
- {dhisana-0.0.1.dist-info → dhisana-0.0.2.dist-info}/METADATA +1 -1
- {dhisana-0.0.1.dist-info → dhisana-0.0.2.dist-info}/RECORD +8 -8
- {dhisana-0.0.1.dist-info → dhisana-0.0.2.dist-info}/WHEEL +0 -0
- {dhisana-0.0.1.dist-info → dhisana-0.0.2.dist-info}/entry_points.txt +0 -0
- {dhisana-0.0.1.dist-info → dhisana-0.0.2.dist-info}/top_level.txt +0 -0
dhisana/utils/agent_tools.py
CHANGED
|
@@ -4,15 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
import json
|
|
7
|
-
import re
|
|
8
|
-
import aiohttp
|
|
9
7
|
import uuid
|
|
10
8
|
import io
|
|
11
9
|
import base64
|
|
12
10
|
from bs4 import BeautifulSoup
|
|
13
11
|
from playwright.async_api import async_playwright
|
|
14
12
|
from email.mime.text import MIMEText
|
|
15
|
-
from typing import
|
|
13
|
+
from typing import List, Dict, Any
|
|
16
14
|
from .assistant_tool_tag import assistant_tool
|
|
17
15
|
from google.oauth2 import service_account
|
|
18
16
|
from googleapiclient.discovery import build
|
|
@@ -22,90 +20,9 @@ from google.auth.transport.requests import Request
|
|
|
22
20
|
from typing import List
|
|
23
21
|
from googleapiclient.errors import HttpError
|
|
24
22
|
|
|
25
|
-
|
|
26
23
|
GLOBAL_DATA_MODELS = []
|
|
27
24
|
GLOBAL_TOOLS_FUNCTIONS = {}
|
|
28
25
|
|
|
29
|
-
@assistant_tool
|
|
30
|
-
async def search_google_maps(query):
|
|
31
|
-
SERPAPI_API_KEY = os.getenv('SERPAPI_KEY')
|
|
32
|
-
params = {
|
|
33
|
-
'engine': 'google_maps',
|
|
34
|
-
'q': query,
|
|
35
|
-
'num': 20,
|
|
36
|
-
'api_key': SERPAPI_API_KEY
|
|
37
|
-
}
|
|
38
|
-
async with aiohttp.ClientSession() as session:
|
|
39
|
-
async with session.get('https://serpapi.com/search', params=params) as response:
|
|
40
|
-
output = await response.json()
|
|
41
|
-
print(output)
|
|
42
|
-
return output
|
|
43
|
-
|
|
44
|
-
@assistant_tool
|
|
45
|
-
async def enrich_people_with_apollo(lead_list):
|
|
46
|
-
APOLLO_API_KEY = os.getenv('APOLLO_API_KEY')
|
|
47
|
-
api_url = "https://api.apollo.io/api/v1/people/bulk_match"
|
|
48
|
-
headers = {
|
|
49
|
-
"Content-Type": "application/json",
|
|
50
|
-
"X-Api-Key": APOLLO_API_KEY
|
|
51
|
-
}
|
|
52
|
-
payload = {
|
|
53
|
-
"details": [
|
|
54
|
-
{
|
|
55
|
-
key: lead[key] for key in [
|
|
56
|
-
"first_name", "last_name", "name", "email", "hashed_email",
|
|
57
|
-
"organization_name", "domain", "id", "linkedin_url"
|
|
58
|
-
] if key in lead
|
|
59
|
-
} for lead in lead_list
|
|
60
|
-
if any(lead.get(k) for k in ("first_name", "last_name", "name"))
|
|
61
|
-
],
|
|
62
|
-
"reveal_personal_emails": True
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if not payload["details"]:
|
|
66
|
-
return []
|
|
67
|
-
|
|
68
|
-
try:
|
|
69
|
-
async with aiohttp.ClientSession() as session:
|
|
70
|
-
async with session.post(api_url, headers=headers, json=payload) as response:
|
|
71
|
-
response.raise_for_status()
|
|
72
|
-
return await response.json()
|
|
73
|
-
except aiohttp.ClientError as e:
|
|
74
|
-
print(f"Error occurred while enriching data with Apollo.io: {e}")
|
|
75
|
-
return []
|
|
76
|
-
|
|
77
|
-
@assistant_tool
|
|
78
|
-
async def search_google(query):
|
|
79
|
-
return await _search_serpapi('google', query, 20)
|
|
80
|
-
|
|
81
|
-
@assistant_tool
|
|
82
|
-
async def search_google_jobs(query):
|
|
83
|
-
return await _search_serpapi('google_jobs', query, 20)
|
|
84
|
-
|
|
85
|
-
@assistant_tool
|
|
86
|
-
async def search_google_news(query):
|
|
87
|
-
return await _search_serpapi('google_news', query)
|
|
88
|
-
|
|
89
|
-
async def _search_serpapi(engine, query, num=20):
|
|
90
|
-
print(f"Searching {engine.replace('_', ' ').title()} for: {query}")
|
|
91
|
-
SERPAPI_API_KEY = os.getenv('SERPAPI_KEY')
|
|
92
|
-
params = {
|
|
93
|
-
'engine': engine,
|
|
94
|
-
'q': query,
|
|
95
|
-
'num': num,
|
|
96
|
-
'api_key': SERPAPI_API_KEY
|
|
97
|
-
}
|
|
98
|
-
try:
|
|
99
|
-
async with aiohttp.ClientSession() as session:
|
|
100
|
-
async with session.get('https://serpapi.com/search', params=params) as response:
|
|
101
|
-
response.raise_for_status()
|
|
102
|
-
output = await response.json()
|
|
103
|
-
print(output)
|
|
104
|
-
return output
|
|
105
|
-
except aiohttp.ClientError as e:
|
|
106
|
-
print(f"Error occurred while searching {engine}: {e}")
|
|
107
|
-
return {}
|
|
108
|
-
|
|
109
26
|
@assistant_tool
|
|
110
27
|
async def get_html_content_from_url(url):
|
|
111
28
|
# Check and replace http with https
|
|
@@ -128,7 +45,6 @@ async def get_html_content_from_url(url):
|
|
|
128
45
|
finally:
|
|
129
46
|
await browser.close()
|
|
130
47
|
|
|
131
|
-
@assistant_tool
|
|
132
48
|
async def parse_html_content(html_content):
|
|
133
49
|
if not html_content:
|
|
134
50
|
return ""
|
|
@@ -137,250 +53,6 @@ async def parse_html_content(html_content):
|
|
|
137
53
|
element.decompose()
|
|
138
54
|
return soup.get_text(separator=' ', strip=True)
|
|
139
55
|
|
|
140
|
-
@assistant_tool
|
|
141
|
-
async def extract_image_links(html_content):
|
|
142
|
-
soup = BeautifulSoup(html_content, 'html.parser')
|
|
143
|
-
return [{'src': img.get('src'), 'alt': img.get('alt', '')} for img in soup.find_all('img')]
|
|
144
|
-
|
|
145
|
-
@assistant_tool
|
|
146
|
-
async def extract_head_section_from_html_content(html_content):
|
|
147
|
-
soup = BeautifulSoup(html_content, 'html.parser')
|
|
148
|
-
return str(soup.head) if soup.head else ""
|
|
149
|
-
|
|
150
|
-
@assistant_tool
|
|
151
|
-
async def get_email_if_exists(website_content):
|
|
152
|
-
email_pattern = r'(mailto:)?[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
|
|
153
|
-
match = re.search(email_pattern, website_content)
|
|
154
|
-
if match:
|
|
155
|
-
start_index = max(0, match.start() - 7)
|
|
156
|
-
end_index = min(len(website_content), match.end() + 7)
|
|
157
|
-
return website_content[start_index:end_index]
|
|
158
|
-
return ""
|
|
159
|
-
|
|
160
|
-
@assistant_tool
|
|
161
|
-
async def search_crunchbase(query):
|
|
162
|
-
api_url = "https://api.crunchbase.com/api/v4/searches/organizations"
|
|
163
|
-
CRUNCHBASE_API_KEY = os.getenv('CRUNCHBASE_API_KEY')
|
|
164
|
-
headers = {
|
|
165
|
-
"Content-Type": "application/json",
|
|
166
|
-
"X-Cb-User-Key": CRUNCHBASE_API_KEY
|
|
167
|
-
}
|
|
168
|
-
payload = {
|
|
169
|
-
"query": {
|
|
170
|
-
"field_id": "organizations.name",
|
|
171
|
-
"operator_id": "contains",
|
|
172
|
-
"value": query
|
|
173
|
-
},
|
|
174
|
-
"field_ids": [
|
|
175
|
-
"identifier", "name", "short_description", "website", "linkedin",
|
|
176
|
-
"twitter", "location_identifiers", "categories", "num_employees_enum",
|
|
177
|
-
"founded_on", "last_funding_type", "last_funding_total"
|
|
178
|
-
],
|
|
179
|
-
"limit": 5
|
|
180
|
-
}
|
|
181
|
-
try:
|
|
182
|
-
async with aiohttp.ClientSession() as session:
|
|
183
|
-
async with session.post(api_url, headers=headers, json=payload) as response:
|
|
184
|
-
response.raise_for_status()
|
|
185
|
-
return await response.json()
|
|
186
|
-
except aiohttp.ClientError as e:
|
|
187
|
-
print(f"Error occurred while searching Crunchbase: {e}")
|
|
188
|
-
return {}
|
|
189
|
-
|
|
190
|
-
@assistant_tool
|
|
191
|
-
async def search_people_with_apollo(
|
|
192
|
-
person_titles: Optional[Union[str, List[str]]] = None,
|
|
193
|
-
q_keywords: Optional[str] = None,
|
|
194
|
-
person_locations: Optional[Union[str, List[str]]] = None,
|
|
195
|
-
person_seniorities: Optional[Union[str, List[str]]] = None,
|
|
196
|
-
organization_locations: Optional[Union[str, List[str]]] = None,
|
|
197
|
-
organization_num_employees_ranges: Optional[Union[str, List[str]]] = None,
|
|
198
|
-
q_organization_domains: Optional[Union[str, List[str]]] = None,
|
|
199
|
-
) -> Dict[str, Any]:
|
|
200
|
-
"""
|
|
201
|
-
Search for people on Apollo.io using various filters.
|
|
202
|
-
|
|
203
|
-
Args:
|
|
204
|
-
person_titles (str or List[str], optional): Titles of the person to filter by (e.g., ['Sales Manager', 'Engineer', 'Director']).
|
|
205
|
-
q_keywords (str, optional): A string of words over which we want to filter the results (e.g., "Operations Manager, Production Manager").
|
|
206
|
-
person_locations (str or List[str], optional): Locations of the person to filter by (e.g., ['California, US', 'Minnesota, US']).
|
|
207
|
-
person_seniorities (str or List[str], optional): Seniorities or levels (e.g., ['manager', 'director', 'ceo']).
|
|
208
|
-
organization_locations (str or List[str], optional): Locations of the organization (e.g., ['Minnesota, US', 'California, US']).
|
|
209
|
-
organization_num_employees_ranges (str or List[str], optional): Employee size ranges of the organization ["101,200", "200,500"]). Default is Empty.
|
|
210
|
-
q_organization_domains (str or List[str], optional): Domains of the organizations to filter by (e.g., ['apollo.io', 'facebook.com']). Organization domain is company domain like facebook.com .
|
|
211
|
-
Returns:
|
|
212
|
-
Dict[str, Any]: The response from Apollo.io containing the search results, or an empty dict on failure.
|
|
213
|
-
"""
|
|
214
|
-
|
|
215
|
-
api_url = "https://api.apollo.io/v1/mixed_people/search"
|
|
216
|
-
APOLLO_API_KEY = os.getenv('APOLLO_API_KEY')
|
|
217
|
-
headers = {
|
|
218
|
-
"Content-Type": "application/json",
|
|
219
|
-
"Cache-Control": "no-cache",
|
|
220
|
-
"X-Api-Key": APOLLO_API_KEY # Ensure APOLLO_API_KEY is defined
|
|
221
|
-
}
|
|
222
|
-
payload = {}
|
|
223
|
-
|
|
224
|
-
if person_titles:
|
|
225
|
-
if isinstance(person_titles, str):
|
|
226
|
-
person_titles = [person_titles]
|
|
227
|
-
payload["person_titles"] = person_titles
|
|
228
|
-
|
|
229
|
-
if person_locations:
|
|
230
|
-
if isinstance(person_locations, str):
|
|
231
|
-
person_locations = [person_locations]
|
|
232
|
-
payload["person_locations"] = person_locations
|
|
233
|
-
|
|
234
|
-
if person_seniorities:
|
|
235
|
-
if isinstance(person_seniorities, str):
|
|
236
|
-
person_seniorities = [person_seniorities]
|
|
237
|
-
payload["person_seniorities"] = person_seniorities
|
|
238
|
-
|
|
239
|
-
if organization_locations:
|
|
240
|
-
if isinstance(organization_locations, str):
|
|
241
|
-
organization_locations = [organization_locations]
|
|
242
|
-
payload["organization_locations"] = organization_locations
|
|
243
|
-
|
|
244
|
-
if q_organization_domains:
|
|
245
|
-
if isinstance(q_organization_domains, str):
|
|
246
|
-
q_organization_domains = [q_organization_domains]
|
|
247
|
-
payload["q_organization_domains"] = '\n'.join(q_organization_domains)
|
|
248
|
-
|
|
249
|
-
try:
|
|
250
|
-
async with aiohttp.ClientSession() as session:
|
|
251
|
-
async with session.post(api_url, headers=headers, json=payload) as response:
|
|
252
|
-
response.raise_for_status()
|
|
253
|
-
output = await response.json()
|
|
254
|
-
return output
|
|
255
|
-
except aiohttp.ClientError as e:
|
|
256
|
-
print(f"Error occurred while searching for people on Apollo.io: {e}")
|
|
257
|
-
return {}
|
|
258
|
-
|
|
259
|
-
@assistant_tool
|
|
260
|
-
async def search_companies_with_apollo(
|
|
261
|
-
locations: Optional[Union[str, List[str]]] = None,
|
|
262
|
-
industries: Optional[Union[str, List[str]]] = None,
|
|
263
|
-
employee_size_ranges: Optional[Union[str, List[str]]] = None
|
|
264
|
-
) -> Dict[str, Any]:
|
|
265
|
-
"""
|
|
266
|
-
Search for companies on Apollo.io using various filters.
|
|
267
|
-
|
|
268
|
-
Args:
|
|
269
|
-
locations (str or List[str], optional): Locations of the company (city, state, country). (e.g., 'San Jose', ['Seattle', 'New York']).
|
|
270
|
-
industries (str or List[str], optional): Industry sectors of the company. (e.g., 'Manufacturing', ['Bio Medical', 'async defense']).
|
|
271
|
-
employee_size_range (str, optional): Employee size of company to filter by eg (e.g., '50,100', ["1,10", "101,200" ]).
|
|
272
|
-
|
|
273
|
-
Returns:
|
|
274
|
-
Dict[str, Any]: The response from Apollo.io containing the search results, or an empty dict on failure.
|
|
275
|
-
"""
|
|
276
|
-
api_url = "https://api.apollo.io/api/v1/mixed_companies/search"
|
|
277
|
-
APOLLO_API_KEY = os.getenv('APOLLO_API_KEY')
|
|
278
|
-
headers = {
|
|
279
|
-
"Content-Type": "application/json",
|
|
280
|
-
"Cache-Control": "no-cache",
|
|
281
|
-
"X-Api-Key": APOLLO_API_KEY
|
|
282
|
-
}
|
|
283
|
-
payload = {
|
|
284
|
-
"per_page": 10,
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if employee_size_ranges:
|
|
288
|
-
if isinstance(employee_size_ranges, str):
|
|
289
|
-
employee_size_ranges = [employee_size_ranges]
|
|
290
|
-
payload["organization_num_employees_ranges"] = employee_size_ranges
|
|
291
|
-
|
|
292
|
-
# Handle location
|
|
293
|
-
if locations:
|
|
294
|
-
if isinstance(locations, str):
|
|
295
|
-
locations = [loc.strip() for loc in locations.split(',')]
|
|
296
|
-
payload["organization_locations"] = locations
|
|
297
|
-
|
|
298
|
-
# Handle industry
|
|
299
|
-
if industries:
|
|
300
|
-
if isinstance(industries, str):
|
|
301
|
-
industries = [ind.strip() for ind in industries.split(',')]
|
|
302
|
-
payload["q_organization_keyword_tags"] = industries
|
|
303
|
-
|
|
304
|
-
try:
|
|
305
|
-
async with aiohttp.ClientSession() as session:
|
|
306
|
-
async with session.post(api_url, headers=headers, json=payload) as response:
|
|
307
|
-
response.raise_for_status()
|
|
308
|
-
return await response.json()
|
|
309
|
-
except aiohttp.ClientError as e:
|
|
310
|
-
print(f"Error occurred while searching for companies on Apollo.io: {e}")
|
|
311
|
-
return {}
|
|
312
|
-
|
|
313
|
-
@assistant_tool
|
|
314
|
-
async def enrich_company_with_apollo(
|
|
315
|
-
company_domain: str = None,
|
|
316
|
-
) -> Dict[str, Any]:
|
|
317
|
-
"""
|
|
318
|
-
Enrich company information using Apollo.io.
|
|
319
|
-
|
|
320
|
-
Args:
|
|
321
|
-
company_domain (str, optional): The domain of the company (e.g., 'example.com').
|
|
322
|
-
|
|
323
|
-
Returns:
|
|
324
|
-
Dict[str, Any]: The enriched company information from Apollo.io, or an empty dict on failure.
|
|
325
|
-
"""
|
|
326
|
-
api_url = "https://api.apollo.io/v1/organizations/enrich"
|
|
327
|
-
APOLLO_API_KEY = os.getenv('APOLLO_API_KEY')
|
|
328
|
-
headers = {
|
|
329
|
-
"Content-Type": "application/json",
|
|
330
|
-
"Cache-Control": "no-cache",
|
|
331
|
-
"X-Api-Key": APOLLO_API_KEY
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if not company_domain:
|
|
335
|
-
return ""
|
|
336
|
-
params = {"domain": company_domain}
|
|
337
|
-
|
|
338
|
-
try:
|
|
339
|
-
async with aiohttp.ClientSession() as session:
|
|
340
|
-
async with session.get(api_url, headers=headers, params=params) as response:
|
|
341
|
-
response.raise_for_status()
|
|
342
|
-
output = await response.json()
|
|
343
|
-
return output
|
|
344
|
-
except aiohttp.ClientError as e:
|
|
345
|
-
print(f"Error occurred while enriching company info on Apollo.io: {e}")
|
|
346
|
-
return {}
|
|
347
|
-
|
|
348
|
-
@assistant_tool
|
|
349
|
-
async def get_job_postings_from_apollo(
|
|
350
|
-
organization_id: str = None,
|
|
351
|
-
) -> List[Dict[str, Any]]:
|
|
352
|
-
"""
|
|
353
|
-
Get a list of active job postings for a company using Apollo.io.
|
|
354
|
-
|
|
355
|
-
Args:
|
|
356
|
-
organization_id (str, optional): The ID of the organization.
|
|
357
|
-
|
|
358
|
-
Returns:
|
|
359
|
-
List[Dict[str, Any]]: The list of job postings from Apollo.io, or an empty list on failure.
|
|
360
|
-
"""
|
|
361
|
-
api_url = f"https://api.apollo.io/v1/organizations/{organization_id}/job_postings"
|
|
362
|
-
APOLLO_API_KEY = os.getenv('APOLLO_API_KEY')
|
|
363
|
-
headers = {
|
|
364
|
-
"Content-Type": "application/json",
|
|
365
|
-
"Cache-Control": "no-cache",
|
|
366
|
-
"X-Api-Key": APOLLO_API_KEY # Ensure you have the API key set up.
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
if not organization_id:
|
|
370
|
-
raise ValueError("organization_id must be provided.")
|
|
371
|
-
|
|
372
|
-
try:
|
|
373
|
-
async with aiohttp.ClientSession() as session:
|
|
374
|
-
async with session.get(api_url, headers=headers) as response:
|
|
375
|
-
response.raise_for_status()
|
|
376
|
-
output = (await response.json()).get("organization_job_postings", [])
|
|
377
|
-
print(output)
|
|
378
|
-
return output
|
|
379
|
-
except aiohttp.ClientError as e:
|
|
380
|
-
print(f"Error occurred while fetching job postings from Apollo.io: {e}")
|
|
381
|
-
return []
|
|
382
|
-
|
|
383
|
-
|
|
384
56
|
def convert_base_64_json(base64_string):
|
|
385
57
|
"""
|
|
386
58
|
Convert a base64 encoded string to a JSON string.
|
dhisana/utils/openai_helpers.py
CHANGED
|
@@ -14,8 +14,11 @@ from .tools_json import GLOBAL_ASSISTANT_TOOLS
|
|
|
14
14
|
from .openapi_spec_to_tools import OPENAPI_TOOL_CONFIGURATIONS, OPENAPI_GLOBAL_ASSISTANT_TOOLS, OPENAPI_CALLABALE_FUNCTIONS
|
|
15
15
|
|
|
16
16
|
def get_headers(toolname):
|
|
17
|
-
|
|
18
|
-
headers
|
|
17
|
+
headers = OPENAPI_TOOL_CONFIGURATIONS.get(toolname, {}).get("headers", {})
|
|
18
|
+
return headers
|
|
19
|
+
|
|
20
|
+
def get_params(toolname):
|
|
21
|
+
headers = OPENAPI_TOOL_CONFIGURATIONS.get(toolname, {}).get("params", {})
|
|
19
22
|
return headers
|
|
20
23
|
|
|
21
24
|
async def run_assistant(client, assistant, thread, prompt, response_type, allowed_tools):
|
|
@@ -114,14 +117,14 @@ def get_function(function_name):
|
|
|
114
117
|
async def invoke_function(function, tool, openai_function):
|
|
115
118
|
try:
|
|
116
119
|
function_args = json.loads(tool.function.arguments)
|
|
117
|
-
print(f"Invoking function {tool.function.name} with args: {function_args}")
|
|
120
|
+
print(f"Invoking function {tool.function.name} with args: {function_args}\n")
|
|
118
121
|
if openai_function:
|
|
119
122
|
output = invoke_openai_function(function, function_args, tool.function.name)
|
|
120
123
|
else:
|
|
121
124
|
output = await function(**function_args)
|
|
122
125
|
output_str = json.dumps(output)
|
|
123
|
-
print(output_str)
|
|
124
126
|
output_size = len(output_str.encode('utf-8'))
|
|
127
|
+
print(f"\nOutput from function {tool.function.name}: {output_str[:64]}\n")
|
|
125
128
|
return output_str, output_size
|
|
126
129
|
except Exception as e:
|
|
127
130
|
print(f"Error invoking function {tool.function.name}: {e}")
|
|
@@ -129,11 +132,15 @@ async def invoke_function(function, tool, openai_function):
|
|
|
129
132
|
|
|
130
133
|
|
|
131
134
|
def invoke_openai_function(function, function_args, function_name):
|
|
132
|
-
|
|
135
|
+
|
|
133
136
|
json_body = function_args.get("json", None)
|
|
134
137
|
path_params = function_args.get("path_params", None)
|
|
135
138
|
fn_args = {"path_params": path_params, "data": json_body}
|
|
136
139
|
headers = get_headers(function_name)
|
|
140
|
+
|
|
141
|
+
query_params = function_args.get("params", {})
|
|
142
|
+
params = get_params(function_name)
|
|
143
|
+
query_params.update(params)
|
|
137
144
|
|
|
138
145
|
output_fn = function(
|
|
139
146
|
name=function_name,
|
|
@@ -141,6 +148,7 @@ def invoke_openai_function(function, function_args, function_name):
|
|
|
141
148
|
headers=headers,
|
|
142
149
|
params=query_params,
|
|
143
150
|
)
|
|
151
|
+
print(f"\nOutput from function {function_name}: {output_fn.status_code} {output_fn.reason}\n")
|
|
144
152
|
return {
|
|
145
153
|
"status_code": output_fn.status_code,
|
|
146
154
|
"text": output_fn.text,
|
|
@@ -150,7 +158,6 @@ def invoke_openai_function(function, function_args, function_name):
|
|
|
150
158
|
|
|
151
159
|
def submit_tool_outputs(client, thread, run, tool_outputs):
|
|
152
160
|
try:
|
|
153
|
-
print("calling tool")
|
|
154
161
|
return client.beta.threads.runs.submit_tool_outputs_and_poll(
|
|
155
162
|
thread_id=thread.id,
|
|
156
163
|
run_id=run.id,
|
|
@@ -204,8 +211,11 @@ def get_structured_output(message: str, response_type):
|
|
|
204
211
|
logging.error(f"Unexpected error: {e}")
|
|
205
212
|
raise HTTPException(status_code=500, detail="An unexpected error occurred while processing your request.")
|
|
206
213
|
|
|
214
|
+
class RowItem(BaseModel):
|
|
215
|
+
column_value: str
|
|
216
|
+
|
|
207
217
|
class ResponseList(BaseModel):
|
|
208
|
-
rows: List[
|
|
218
|
+
rows: List[RowItem]
|
|
209
219
|
|
|
210
220
|
def lookup_response_type(name: str):
|
|
211
221
|
for model in GLOBAL_DATA_MODELS:
|
|
@@ -234,10 +244,12 @@ async def process_agent_request(row_batch: List[Dict], steps: Dict, custom_instr
|
|
|
234
244
|
input_data = json.dumps(row)
|
|
235
245
|
output = {}
|
|
236
246
|
for step in steps['steps']:
|
|
237
|
-
type = step
|
|
247
|
+
type = step.get("response_type", None)
|
|
238
248
|
if not type:
|
|
239
249
|
type = "ResponseList"
|
|
240
|
-
|
|
250
|
+
response_type = ResponseList
|
|
251
|
+
else:
|
|
252
|
+
response_type = lookup_response_type(step.get("response_type", None))
|
|
241
253
|
if not response_type:
|
|
242
254
|
response_type = ResponseList
|
|
243
255
|
allowed_tools = step.get("allowed_tools", [])
|
dhisana/utils/tools_json.py
CHANGED
|
@@ -1,206 +1,4 @@
|
|
|
1
1
|
GLOBAL_ASSISTANT_TOOLS = [
|
|
2
|
-
{
|
|
3
|
-
"type": "function",
|
|
4
|
-
"function": {
|
|
5
|
-
"name": "search_google_maps",
|
|
6
|
-
"description": "Search for locations on Google Maps.",
|
|
7
|
-
"parameters": {
|
|
8
|
-
"type": "object",
|
|
9
|
-
"properties": {
|
|
10
|
-
"query": {
|
|
11
|
-
"type": "string",
|
|
12
|
-
"description": "The search query, e.g., 'restaurants in New York'."
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"required": ["query"],
|
|
16
|
-
"additionalProperties": False
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"type": "function",
|
|
22
|
-
"function": {
|
|
23
|
-
"name": "enrich_company_with_apollo",
|
|
24
|
-
"description": "Enrich company information with information in apollo.",
|
|
25
|
-
"parameters": {
|
|
26
|
-
"type": "object",
|
|
27
|
-
"properties": {
|
|
28
|
-
"company_domain": {
|
|
29
|
-
"type": "string",
|
|
30
|
-
"description": "website domain of the company'."
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"required": ["company_domain"],
|
|
34
|
-
"additionalProperties": False
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"type": "function",
|
|
40
|
-
"function": {
|
|
41
|
-
"name": "get_job_postings_from_apollo",
|
|
42
|
-
"description": "Get a list of active job postings for a company using Apollo.io.",
|
|
43
|
-
"parameters": {
|
|
44
|
-
"type": "object",
|
|
45
|
-
"properties": {
|
|
46
|
-
"organization_id": {
|
|
47
|
-
"type": "string",
|
|
48
|
-
"description": "The ID of the organization."
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
"required": ["organization_id"],
|
|
52
|
-
"additionalProperties": False
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"type": "function",
|
|
58
|
-
"function": {
|
|
59
|
-
"name": "search_companies_with_apollo",
|
|
60
|
-
"description": "Search for companies on Apollo.io using various filters.",
|
|
61
|
-
"parameters": {
|
|
62
|
-
"type": "object",
|
|
63
|
-
"properties": {
|
|
64
|
-
"locations": {
|
|
65
|
-
"anyOf": [
|
|
66
|
-
{ "type": "string" },
|
|
67
|
-
{ "type": "array", "items": { "type": "string" } }
|
|
68
|
-
],
|
|
69
|
-
"description": "Locations to filter by. (e.g., 'San Jose', ['Seattle', 'New York'])"
|
|
70
|
-
},
|
|
71
|
-
"industries": {
|
|
72
|
-
"anyOf": [
|
|
73
|
-
{ "type": "string" },
|
|
74
|
-
{ "type": "array", "items": { "type": "string" } }
|
|
75
|
-
],
|
|
76
|
-
"description": "Industry sectors to filter by. (e.g., 'Manufacturing', ['Bio Medical', 'Defense'])"
|
|
77
|
-
},
|
|
78
|
-
"employee_size_ranges": {
|
|
79
|
-
"anyOf": [
|
|
80
|
-
{ "type": "string" },
|
|
81
|
-
{ "type": "array", "items": { "type": "string" } }
|
|
82
|
-
],
|
|
83
|
-
"description": "Employee size of company to filter by eg (e.g., '50,100', ['1,10', '101,200' ])."
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
"required": [],
|
|
87
|
-
"additionalProperties": False
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"type": "function",
|
|
93
|
-
"function": {
|
|
94
|
-
"name": "enrich_people_with_apollo",
|
|
95
|
-
"description": "Enrich a list of people's information using Apollo.io.",
|
|
96
|
-
"parameters": {
|
|
97
|
-
"type": "object",
|
|
98
|
-
"properties": {
|
|
99
|
-
"lead_list": {
|
|
100
|
-
"type": "array",
|
|
101
|
-
"items": {
|
|
102
|
-
"type": "object",
|
|
103
|
-
"properties": {
|
|
104
|
-
"first_name": {
|
|
105
|
-
"type": "string",
|
|
106
|
-
"description": "The person's first name."
|
|
107
|
-
},
|
|
108
|
-
"last_name": {
|
|
109
|
-
"type": "string",
|
|
110
|
-
"description": "The person's last name."
|
|
111
|
-
},
|
|
112
|
-
"name": {
|
|
113
|
-
"type": "string",
|
|
114
|
-
"description": "The person's full name."
|
|
115
|
-
},
|
|
116
|
-
"email": {
|
|
117
|
-
"type": "string",
|
|
118
|
-
"description": "The person's email address."
|
|
119
|
-
},
|
|
120
|
-
"hashed_email": {
|
|
121
|
-
"type": "string",
|
|
122
|
-
"description": "The hashed email of the person."
|
|
123
|
-
},
|
|
124
|
-
"organization_name": {
|
|
125
|
-
"type": "string",
|
|
126
|
-
"description": "The person's organization name."
|
|
127
|
-
},
|
|
128
|
-
"domain": {
|
|
129
|
-
"type": "string",
|
|
130
|
-
"description": "The organization's domain name."
|
|
131
|
-
},
|
|
132
|
-
"id": {
|
|
133
|
-
"type": "string",
|
|
134
|
-
"description": "The person's unique identifier."
|
|
135
|
-
},
|
|
136
|
-
"linkedin_url": {
|
|
137
|
-
"type": "string",
|
|
138
|
-
"description": "The person's LinkedIn URL."
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
"additionalProperties": False
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
"required": ["lead_list"],
|
|
146
|
-
"additionalProperties": False
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
"type": "function",
|
|
152
|
-
"function": {
|
|
153
|
-
"name": "search_google",
|
|
154
|
-
"description": "Search for information on Google Search.",
|
|
155
|
-
"parameters": {
|
|
156
|
-
"type": "object",
|
|
157
|
-
"properties": {
|
|
158
|
-
"query": {
|
|
159
|
-
"type": "string",
|
|
160
|
-
"description": "The search query, e.g., 'weather tomorrow'."
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
|
-
"required": ["query"],
|
|
164
|
-
"additionalProperties": False
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
{
|
|
169
|
-
"type": "function",
|
|
170
|
-
"function": {
|
|
171
|
-
"name": "search_google_jobs",
|
|
172
|
-
"description": "Search for jobs on Google Jobs.",
|
|
173
|
-
"parameters": {
|
|
174
|
-
"type": "object",
|
|
175
|
-
"properties": {
|
|
176
|
-
"query": {
|
|
177
|
-
"type": "string",
|
|
178
|
-
"description": "The search query, e.g., 'software engineer jobs in San Francisco'."
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
"required": ["query"],
|
|
182
|
-
"additionalProperties": False
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
"type": "function",
|
|
188
|
-
"function": {
|
|
189
|
-
"name": "search_google_news",
|
|
190
|
-
"description": "Search for news articles on Google News.",
|
|
191
|
-
"parameters": {
|
|
192
|
-
"type": "object",
|
|
193
|
-
"properties": {
|
|
194
|
-
"query": {
|
|
195
|
-
"type": "string",
|
|
196
|
-
"description": "The search query, e.g., 'latest tech news'."
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
|
-
"required": ["query"],
|
|
200
|
-
"additionalProperties": False
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
2
|
{
|
|
205
3
|
"type": "function",
|
|
206
4
|
"function": {
|
|
@@ -219,156 +17,6 @@ GLOBAL_ASSISTANT_TOOLS = [
|
|
|
219
17
|
}
|
|
220
18
|
}
|
|
221
19
|
},
|
|
222
|
-
{
|
|
223
|
-
"type": "function",
|
|
224
|
-
"function": {
|
|
225
|
-
"name": "parse_html_content",
|
|
226
|
-
"description": "Parse HTML content and extract text.",
|
|
227
|
-
"parameters": {
|
|
228
|
-
"type": "object",
|
|
229
|
-
"properties": {
|
|
230
|
-
"html_content": {
|
|
231
|
-
"type": "string",
|
|
232
|
-
"description": "The HTML content to parse."
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
"required": ["html_content"],
|
|
236
|
-
"additionalProperties": False
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
"type": "function",
|
|
242
|
-
"function": {
|
|
243
|
-
"name": "extract_image_links",
|
|
244
|
-
"description": "Extract image links from HTML content.",
|
|
245
|
-
"parameters": {
|
|
246
|
-
"type": "object",
|
|
247
|
-
"properties": {
|
|
248
|
-
"html_content": {
|
|
249
|
-
"type": "string",
|
|
250
|
-
"description": "The HTML content to parse."
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
"required": ["html_content"],
|
|
254
|
-
"additionalProperties": False
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
"type": "function",
|
|
260
|
-
"function": {
|
|
261
|
-
"name": "extract_head_section_from_html_content",
|
|
262
|
-
"description": "Extract the <head> section from HTML content.",
|
|
263
|
-
"parameters": {
|
|
264
|
-
"type": "object",
|
|
265
|
-
"properties": {
|
|
266
|
-
"html_content": {
|
|
267
|
-
"type": "string",
|
|
268
|
-
"description": "The HTML content to parse."
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
"required": ["html_content"],
|
|
272
|
-
"additionalProperties": False
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
"type": "function",
|
|
278
|
-
"function": {
|
|
279
|
-
"name": "get_email_if_exists",
|
|
280
|
-
"description": "Extract an email address if it exists in the given content.",
|
|
281
|
-
"parameters": {
|
|
282
|
-
"type": "object",
|
|
283
|
-
"properties": {
|
|
284
|
-
"website_content": {
|
|
285
|
-
"type": "string",
|
|
286
|
-
"description": "The text content to search for an email address."
|
|
287
|
-
}
|
|
288
|
-
},
|
|
289
|
-
"required": ["website_content"],
|
|
290
|
-
"additionalProperties": False
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
"type": "function",
|
|
296
|
-
"function": {
|
|
297
|
-
"name": "search_crunchbase",
|
|
298
|
-
"description": "Search for organizations on Crunchbase.",
|
|
299
|
-
"parameters": {
|
|
300
|
-
"type": "object",
|
|
301
|
-
"properties": {
|
|
302
|
-
"query": {
|
|
303
|
-
"type": "string",
|
|
304
|
-
"description": "The organization name to search for."
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
"required": ["query"],
|
|
308
|
-
"additionalProperties": False
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
"type": "function",
|
|
314
|
-
"function": {
|
|
315
|
-
"name": "search_people_with_apollo",
|
|
316
|
-
"description": "Search for people on Apollo.io using various filters.",
|
|
317
|
-
"parameters": {
|
|
318
|
-
"type": "object",
|
|
319
|
-
"properties": {
|
|
320
|
-
"person_titles": {
|
|
321
|
-
"type": ["string", "array"],
|
|
322
|
-
"items": {
|
|
323
|
-
"type": "string"
|
|
324
|
-
},
|
|
325
|
-
"description": "Titles of the person to filter by (e.g., ['Sales Manager', 'Engineer', 'Director'])."
|
|
326
|
-
},
|
|
327
|
-
"q_keywords": {
|
|
328
|
-
"type": "string",
|
|
329
|
-
"description": "A string of words over which we want to filter the results (e.g., 'Operations Manager, Production Manager')."
|
|
330
|
-
},
|
|
331
|
-
"person_locations": {
|
|
332
|
-
"type": ["string", "array"],
|
|
333
|
-
"items": {
|
|
334
|
-
"type": "string"
|
|
335
|
-
},
|
|
336
|
-
"description": "Locations of the person to filter by (e.g., ['California, US', 'Minnesota, US'])."
|
|
337
|
-
},
|
|
338
|
-
"person_seniorities": {
|
|
339
|
-
"type": ["string", "array"],
|
|
340
|
-
"items": {
|
|
341
|
-
"type": "string"
|
|
342
|
-
},
|
|
343
|
-
"description": "Seniorities or levels (e.g., ['manager', 'director', 'ceo'])."
|
|
344
|
-
},
|
|
345
|
-
"organization_locations": {
|
|
346
|
-
"type": ["string", "array"],
|
|
347
|
-
"items": {
|
|
348
|
-
"type": "string"
|
|
349
|
-
},
|
|
350
|
-
"description": "Locations of the organization (e.g., ['Minnesota, US', 'California, US'])."
|
|
351
|
-
},
|
|
352
|
-
"organization_num_employees_ranges": {
|
|
353
|
-
"type": ["string", "array"],
|
|
354
|
-
"items": {
|
|
355
|
-
"type": "string"
|
|
356
|
-
},
|
|
357
|
-
"description": "Employee size ranges of the organization (e.g., ['101,200', '200,500'])."
|
|
358
|
-
},
|
|
359
|
-
"q_organization_domains": {
|
|
360
|
-
"type": ["string", "array"],
|
|
361
|
-
"items": {
|
|
362
|
-
"type": "string"
|
|
363
|
-
},
|
|
364
|
-
"description": "Domains of the organizations to filter by (e.g., ['apollo.io', 'facebook.com']). Organization domain is company domain like facebook.com."
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
"required": [],
|
|
368
|
-
"additionalProperties": False
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
},
|
|
372
20
|
{
|
|
373
21
|
"type": "function",
|
|
374
22
|
"function": {
|
|
@@ -5,17 +5,17 @@ dhisana/cli/datasets.py,sha256=OwzoCrVQqmh0pKpUAKAg_w9uGYncbWU7ZrAL_QukxAk,839
|
|
|
5
5
|
dhisana/cli/models.py,sha256=IzUFZW_X32mL3fpM1_j4q8AF7v5nrxJcxBoqvG-TTgA,706
|
|
6
6
|
dhisana/cli/predictions.py,sha256=VYgoLK1Ksv6MFImoYZqjQJkds7e5Hso65dHwbxTNNzE,646
|
|
7
7
|
dhisana/utils/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
|
|
8
|
-
dhisana/utils/agent_tools.py,sha256=
|
|
8
|
+
dhisana/utils/agent_tools.py,sha256=jNEsaNiBfQnuEWKlGtT6iuFrRCxmEzogGg3mnVoDBeI,15972
|
|
9
9
|
dhisana/utils/assistant_tool_tag.py,sha256=9KG2sSQgBFU-V8kAe6DlTDQ36lQ96BGOLKaVW0zI960,118
|
|
10
|
-
dhisana/utils/openai_helpers.py,sha256=
|
|
10
|
+
dhisana/utils/openai_helpers.py,sha256=R2IBu6IdtYGmpu4mllE8zkK2BbfG--LXXAOC9mpuE1Q,10086
|
|
11
11
|
dhisana/utils/openapi_spec_to_tools.py,sha256=Cx_52re3bBU3--qxBS0X_lKzc0rBWMKFdCCrysgBtso,1393
|
|
12
|
-
dhisana/utils/tools_json.py,sha256=
|
|
12
|
+
dhisana/utils/tools_json.py,sha256=gYGmigdUY1moWvBV9r6yBJbT3cC04IXAtCnMlt4ZUYU,3780
|
|
13
13
|
dhisana/utils/openapi_tool/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
|
|
14
14
|
dhisana/utils/openapi_tool/api_models.py,sha256=Nh6Oi3-UZNYi64b3ZbnrSsAnvK9GGFGUyRMDRJQfOpQ,21288
|
|
15
15
|
dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py,sha256=RZy-PRWmzEHizDNcvqc6PnqwFLbZalvtHJLRkUJuS5g,10127
|
|
16
16
|
dhisana/utils/openapi_tool/openapi_tool.py,sha256=QviFu9SEuRnrAaNVMP-fBolKOJ2iQnvKWkG8AlK9Uks,11000
|
|
17
|
-
dhisana-0.0.
|
|
18
|
-
dhisana-0.0.
|
|
19
|
-
dhisana-0.0.
|
|
20
|
-
dhisana-0.0.
|
|
21
|
-
dhisana-0.0.
|
|
17
|
+
dhisana-0.0.2.dist-info/METADATA,sha256=GE5_4R9bcTXZpDvgd3dbzdDkSbCxAPkK0c49tsUVqtc,725
|
|
18
|
+
dhisana-0.0.2.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
19
|
+
dhisana-0.0.2.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
|
|
20
|
+
dhisana-0.0.2.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
|
|
21
|
+
dhisana-0.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|