dhisana 0.0.1.dev243__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/__init__.py +1 -0
- dhisana/cli/__init__.py +1 -0
- dhisana/cli/cli.py +20 -0
- dhisana/cli/datasets.py +27 -0
- dhisana/cli/models.py +26 -0
- dhisana/cli/predictions.py +20 -0
- dhisana/schemas/__init__.py +1 -0
- dhisana/schemas/common.py +399 -0
- dhisana/schemas/sales.py +965 -0
- dhisana/ui/__init__.py +1 -0
- dhisana/ui/components.py +472 -0
- dhisana/utils/__init__.py +1 -0
- dhisana/utils/add_mapping.py +352 -0
- dhisana/utils/agent_tools.py +51 -0
- dhisana/utils/apollo_tools.py +1597 -0
- dhisana/utils/assistant_tool_tag.py +4 -0
- dhisana/utils/built_with_api_tools.py +282 -0
- dhisana/utils/cache_output_tools.py +98 -0
- dhisana/utils/cache_output_tools_local.py +78 -0
- dhisana/utils/check_email_validity_tools.py +717 -0
- dhisana/utils/check_for_intent_signal.py +107 -0
- dhisana/utils/check_linkedin_url_validity.py +209 -0
- dhisana/utils/clay_tools.py +43 -0
- dhisana/utils/clean_properties.py +135 -0
- dhisana/utils/company_utils.py +60 -0
- dhisana/utils/compose_salesnav_query.py +259 -0
- dhisana/utils/compose_search_query.py +759 -0
- dhisana/utils/compose_three_step_workflow.py +234 -0
- dhisana/utils/composite_tools.py +137 -0
- dhisana/utils/dataframe_tools.py +237 -0
- dhisana/utils/domain_parser.py +45 -0
- dhisana/utils/email_body_utils.py +72 -0
- dhisana/utils/email_parse_helpers.py +132 -0
- dhisana/utils/email_provider.py +375 -0
- dhisana/utils/enrich_lead_information.py +933 -0
- dhisana/utils/extract_email_content_for_llm.py +101 -0
- dhisana/utils/fetch_openai_config.py +129 -0
- dhisana/utils/field_validators.py +426 -0
- dhisana/utils/g2_tools.py +104 -0
- dhisana/utils/generate_content.py +41 -0
- dhisana/utils/generate_custom_message.py +271 -0
- dhisana/utils/generate_email.py +278 -0
- dhisana/utils/generate_email_response.py +465 -0
- dhisana/utils/generate_flow.py +102 -0
- dhisana/utils/generate_leads_salesnav.py +303 -0
- dhisana/utils/generate_linkedin_connect_message.py +224 -0
- dhisana/utils/generate_linkedin_response_message.py +317 -0
- dhisana/utils/generate_structured_output_internal.py +462 -0
- dhisana/utils/google_custom_search.py +267 -0
- dhisana/utils/google_oauth_tools.py +727 -0
- dhisana/utils/google_workspace_tools.py +1294 -0
- dhisana/utils/hubspot_clearbit.py +96 -0
- dhisana/utils/hubspot_crm_tools.py +2440 -0
- dhisana/utils/instantly_tools.py +149 -0
- dhisana/utils/linkedin_crawler.py +168 -0
- dhisana/utils/lusha_tools.py +333 -0
- dhisana/utils/mailgun_tools.py +156 -0
- dhisana/utils/mailreach_tools.py +123 -0
- dhisana/utils/microsoft365_tools.py +455 -0
- dhisana/utils/openai_assistant_and_file_utils.py +267 -0
- dhisana/utils/openai_helpers.py +977 -0
- dhisana/utils/openapi_spec_to_tools.py +45 -0
- dhisana/utils/openapi_tool/__init__.py +1 -0
- dhisana/utils/openapi_tool/api_models.py +633 -0
- dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py +271 -0
- dhisana/utils/openapi_tool/openapi_tool.py +319 -0
- dhisana/utils/parse_linkedin_messages_txt.py +100 -0
- dhisana/utils/profile.py +37 -0
- dhisana/utils/proxy_curl_tools.py +1226 -0
- dhisana/utils/proxycurl_search_leads.py +426 -0
- dhisana/utils/python_function_to_tools.py +83 -0
- dhisana/utils/research_lead.py +176 -0
- dhisana/utils/sales_navigator_crawler.py +1103 -0
- dhisana/utils/salesforce_crm_tools.py +477 -0
- dhisana/utils/search_router.py +131 -0
- dhisana/utils/search_router_jobs.py +51 -0
- dhisana/utils/sendgrid_tools.py +162 -0
- dhisana/utils/serarch_router_local_business.py +75 -0
- dhisana/utils/serpapi_additional_tools.py +290 -0
- dhisana/utils/serpapi_google_jobs.py +117 -0
- dhisana/utils/serpapi_google_search.py +188 -0
- dhisana/utils/serpapi_local_business_search.py +129 -0
- dhisana/utils/serpapi_search_tools.py +852 -0
- dhisana/utils/serperdev_google_jobs.py +125 -0
- dhisana/utils/serperdev_local_business.py +154 -0
- dhisana/utils/serperdev_search.py +233 -0
- dhisana/utils/smtp_email_tools.py +582 -0
- dhisana/utils/test_connect.py +2087 -0
- dhisana/utils/trasform_json.py +173 -0
- dhisana/utils/web_download_parse_tools.py +189 -0
- dhisana/utils/workflow_code_model.py +5 -0
- dhisana/utils/zoominfo_tools.py +357 -0
- dhisana/workflow/__init__.py +1 -0
- dhisana/workflow/agent.py +18 -0
- dhisana/workflow/flow.py +44 -0
- dhisana/workflow/task.py +43 -0
- dhisana/workflow/test.py +90 -0
- dhisana-0.0.1.dev243.dist-info/METADATA +43 -0
- dhisana-0.0.1.dev243.dist-info/RECORD +102 -0
- dhisana-0.0.1.dev243.dist-info/WHEEL +5 -0
- dhisana-0.0.1.dev243.dist-info/entry_points.txt +2 -0
- dhisana-0.0.1.dev243.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
import openai # Remove if not required outside get_structured_output_internal
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from dhisana.utils.generate_structured_output_internal import get_structured_output_internal
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
logging.basicConfig(level=logging.INFO)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SalesNavQuery(BaseModel):
|
|
14
|
+
"""
|
|
15
|
+
Pydantic model representing the final LinkedIn Sales Navigator URL.
|
|
16
|
+
"""
|
|
17
|
+
linkedin_salenav_url_with_query_parameters: str
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def generate_salesnav_people_search_url(
|
|
21
|
+
english_description: str = "",
|
|
22
|
+
user_input_salesnav_url: str = "",
|
|
23
|
+
tool_config: Optional[List[Dict[str, Any]]] = None
|
|
24
|
+
) -> Dict[str, Any]:
|
|
25
|
+
"""
|
|
26
|
+
Generate a single LinkedIn Sales Navigator URL based on the user's plain-English
|
|
27
|
+
description of filters and parameters or a provided Sales Navigator URL.
|
|
28
|
+
|
|
29
|
+
This function leverages an LLM (via get_structured_output_internal) to parse
|
|
30
|
+
the user's requirements (e.g., connection degree, seniority, region, etc.)
|
|
31
|
+
and build a properly encoded Sales Navigator people-search URL.
|
|
32
|
+
|
|
33
|
+
The function handles these scenarios:
|
|
34
|
+
1. Both `english_description` and `user_input_salesnav_url` are provided.
|
|
35
|
+
2. Only `user_input_salesnav_url` is provided (no `english_description`).
|
|
36
|
+
3. Only `english_description` is provided (no `user_input_salesnav_url`).
|
|
37
|
+
4. Neither is provided -> returns an error.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
english_description: A plain-English description of desired filters
|
|
41
|
+
(e.g., "Find me 2nd-degree connections in the IT industry who changed jobs recently").
|
|
42
|
+
user_input_salesnav_url: If the user has provided a Sales Navigator URL to use. (default "").
|
|
43
|
+
tool_config: Optional list of dictionaries containing configuration details
|
|
44
|
+
for the LLM or related tools.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
A dictionary with a single key: "linkedin_salenav_url_with_query_parameters".
|
|
48
|
+
This maps to a string containing the fully qualified Sales Navigator URL.
|
|
49
|
+
|
|
50
|
+
Raises:
|
|
51
|
+
ValueError: If neither english_description nor user_input_salesnav_url is provided.
|
|
52
|
+
Exception: If the LLM call fails or cannot generate a valid URL.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
# Explanation of potential filters to guide the model
|
|
56
|
+
supported_filters_explanation = """
|
|
57
|
+
Sales Navigator filters include (not exhaustive):
|
|
58
|
+
- PAST_COLLEAGUE
|
|
59
|
+
- CURRENT_TITLE
|
|
60
|
+
- PAST_TITLE
|
|
61
|
+
- CURRENT_COMPANY
|
|
62
|
+
- PAST_COMPANY
|
|
63
|
+
- GEOGRAPHY (REGION)
|
|
64
|
+
- INDUSTRY
|
|
65
|
+
- SCHOOL
|
|
66
|
+
- CONNECTION (RELATIONSHIP)
|
|
67
|
+
- CONNECTIONS_OF
|
|
68
|
+
- GROUP
|
|
69
|
+
- COMPANY_HEADCOUNT
|
|
70
|
+
- COMPANY_TYPE
|
|
71
|
+
- SENIORITY_LEVEL
|
|
72
|
+
- YEARS_IN_POSITION
|
|
73
|
+
- YEARS_IN_COMPANY
|
|
74
|
+
- FOLLOWING_YOUR_COMPANY (FOLLOWS_YOUR_COMPANY)
|
|
75
|
+
- VIEWED_YOUR_PROFILE
|
|
76
|
+
- CHANGED_JOBS (RECENTLY_CHANGED_JOBS)
|
|
77
|
+
- POSTED_ON_LINKEDIN
|
|
78
|
+
- MENTIONED_IN_NEWS
|
|
79
|
+
- TECHNOLOGIES_USED
|
|
80
|
+
- ANNUAL_REVENUE
|
|
81
|
+
- LEAD_INTERACTIONS (e.g. Viewed Profile, Messaged)
|
|
82
|
+
- SAVED_LEADS_AND_ACCOUNTS
|
|
83
|
+
- WITH_SHARED_EXPERIENCES
|
|
84
|
+
- FIRST_NAME
|
|
85
|
+
- LAST_NAME
|
|
86
|
+
- FUNCTION
|
|
87
|
+
- YEARS_OF_EXPERIENCE
|
|
88
|
+
- YEARS_AT_CURRENT_COMPANY
|
|
89
|
+
- YEARS_IN_CURRENT_POSITION
|
|
90
|
+
- COMPANY_HEADQUARTERS
|
|
91
|
+
- keywords
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
# System message to guide the LLM
|
|
95
|
+
system_message = (
|
|
96
|
+
"You are a helpful AI Assistant that converts an English description of "
|
|
97
|
+
"LinkedIn Sales Navigator search requirements into a valid LinkedIn Sales Navigator people-search URL. "
|
|
98
|
+
"Your output MUST be a single valid URL with properly encoded parameters. "
|
|
99
|
+
"No extra commentary or text is allowed. If you are unsure about a filter, make your best guess or omit it."
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Examples to help the LLM
|
|
103
|
+
few_examples_of_queries = (
|
|
104
|
+
"\n 1. Below is an example search url with filter -- company headcount 11-500, seniority level CXO, Current Job Title Chief Marketing Officer,"
|
|
105
|
+
"Geography United States, Connection 2nd-degree connections, and Recently Changed jobs: \n"
|
|
106
|
+
"\nhttps://www.linkedin.com/sales/search/people?query="
|
|
107
|
+
"(recentSearchParam%3A(id%3A4390717732%2CdoLogHistory%3Atrue)%2Cfilters%3AList((type%3ACOMPANY_HEADCOUNT%2Cvalues%3AList"
|
|
108
|
+
"((id%3AC%2Ctext%3A11-50%2CselectionType%3AINCLUDED)%2C(id%3AD%2Ctext%3A51-200%2CselectionType%3AINCLUDED)%2C(id%3AE%2Ctext%3A201-500%2CselectionType%3AINCLUDED)))"
|
|
109
|
+
"%2C(type%3ASENIORITY_LEVEL%2Cvalues%3AList((id%3A310%2Ctext%3ACXO%2CselectionType%3AINCLUDED)))%2C(type%3AREGION%2Cvalues%3AList"
|
|
110
|
+
"((id%3A103644278%2Ctext%3AUnited%2520States%2CselectionType%3AINCLUDED)))"
|
|
111
|
+
"%2C(type%3ARECENTLY_CHANGED_JOBS%2Cvalues%3AList((id%3ARPC%2Ctext%3AChanged%2520jobs%2CselectionType%3AINCLUDED)))"
|
|
112
|
+
"%2C(type%3ARELATIONSHIP%2Cvalues%3AList((id%3AS%2Ctext%3A2nd%2520degree%2520connections%2CselectionType%3AINCLUDED)))"
|
|
113
|
+
"%2C(type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A716%2Ctext%3AChief%2520Marketing%2520Officer%2CselectionType%3AINCLUDED)))))\n\n"
|
|
114
|
+
"\n 2. Below is Another example search url with filters -- company headcount 201-500, seniority level CXO, Current Job Title Chief Executive Officer,"
|
|
115
|
+
"Geography United States, Connection 1st-degree connections, and Recently Posted on LinkedIn: \n"
|
|
116
|
+
"https://www.linkedin.com/sales/search/people?query="
|
|
117
|
+
"(recentSearchParam%3A(id%3A4390717732%2CdoLogHistory%3Atrue)%2C"
|
|
118
|
+
"filters%3AList((type%3ACOMPANY_HEADCOUNT%2Cvalues%3AList((id%3AE%2Ctext%3A201-500%2CselectionType%3AINCLUDED)))"
|
|
119
|
+
"%2C(type%3ASENIORITY_LEVEL%2Cvalues%3AList((id%3A310%2Ctext%3ACXO%2CselectionType%3AINCLUDED)))"
|
|
120
|
+
"%2C(type%3AREGION%2Cvalues%3AList((id%3A103644278%2Ctext%3AUnited%2520States%2CselectionType%3AINCLUDED)))"
|
|
121
|
+
"%2C(type%3ARELATIONSHIP%2Cvalues%3AList((id%3AF%2Ctext%3A1st%2520degree%2520connections%2CselectionType%3AINCLUDED)))"
|
|
122
|
+
"%2C(type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A8%2Ctext%3AChief%2520Executive%2520Officer%2CselectionType%3AINCLUDED)))"
|
|
123
|
+
"%2C(type%3APOSTED_ON_LINKEDIN%2Cvalues%3AList((id%3ARPOL%2CselectionType%3AINCLUDED)))))&viewAllFilters=true\n"
|
|
124
|
+
"\n3. Below is example to Exclude people who have viewed your profile recently or messaged recently: \n"
|
|
125
|
+
"https://www.linkedin.com/sales/search/people?query=(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)"
|
|
126
|
+
"%2Cfilters%3AList((type%3ALEAD_INTERACTIONS%2Cvalues%3AList((id%3ALIVP%2Ctext%3AViewed%2520profile%2CselectionType%3AEXCLUDED)"
|
|
127
|
+
"%2C(id%3ALIMP%2Ctext%3AMessaged%2CselectionType%3AEXCLUDED)))"
|
|
128
|
+
"%2C(type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A716%2Ctext%3AChief%2520Marketing%2520Officer%2CselectionType%3AINCLUDED)))))"
|
|
129
|
+
"\n 4. Below is example to exclude people who are in your saved leads or accounts list: \n"
|
|
130
|
+
"https://www.linkedin.com/sales/search/people?query=(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)%2Cfilters%3A"
|
|
131
|
+
"List((type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A716%2Ctext%3AChief%2520Marketing%2520Officer%2CselectionType%3AINCLUDED)))%2C"
|
|
132
|
+
"(type%3ASAVED_LEADS_AND_ACCOUNTS%2Cvalues%3AList((id%3ASL%2Ctext%3AAll%2520my%2520saved%2520leads%2CselectionType%3AEXCLUDED)%2C"
|
|
133
|
+
"(id%3ASA%2Ctext%3AAll%2520my%2520saved%2520accounts%2CselectionType%3AEXCLUDED)))))"
|
|
134
|
+
"\n 5. Below is example to include people with whom you have shared experiences or is past collegue: \n"
|
|
135
|
+
"https://www.linkedin.com/sales/search/people?query=(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)%2C"
|
|
136
|
+
"filters%3AList((type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A716%2Ctext%3AChief%2520Marketing%2520Officer%2CselectionType%3AINCLUDED)))%2C"
|
|
137
|
+
"(type%3AWITH_SHARED_EXPERIENCES%2Cvalues%3AList((id%3ACOMM%2Ctext%3AShared%2520experiences%2CselectionType%3AINCLUDED)))%2C"
|
|
138
|
+
"(type%3ARELATIONSHIP%2Cvalues%3AList((id%3AS%2Ctext%3A2nd%2520degree%2520connections%2CselectionType%3AINCLUDED)))"
|
|
139
|
+
"%2C(type%3APAST_COLLEAGUE%2Cvalues%3AList((id%3APCOLL%2CselectionType%3AINCLUDED)))))"
|
|
140
|
+
"\n 6. Below is example to track leads who viewed your profile recently or followed your company page: \n"
|
|
141
|
+
"https://www.linkedin.com/sales/search/people?query="
|
|
142
|
+
"(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)%2Cfilters%3AList((type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A716%2Ctext%3AChief%2520Marketing%2520Officer%2CselectionType%3AINCLUDED)))"
|
|
143
|
+
"%2C(type%3AVIEWED_YOUR_PROFILE%2Cvalues%3AList((id%3AVYP%2Ctext%3AViewed%2520your%2520profile%2520recently%2CselectionType%3AINCLUDED)))"
|
|
144
|
+
"%2C(type%3AFOLLOWS_YOUR_COMPANY%2Cvalues%3AList((id%3ACF%2CselectionType%3AINCLUDED)))))&viewAllFilters=true"
|
|
145
|
+
"\n 7. Below is example Of somer personal filters like name school industry that can be used: \n"
|
|
146
|
+
"https://www.linkedin.com/sales/search/people?query=(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)"
|
|
147
|
+
"%2Cfilters%3AList((type%3AREGION%2Cvalues%3AList((id%3A102221843%2Ctext%3ANorth%2520America%2CselectionType%3AINCLUDED)))"
|
|
148
|
+
"%2C(type%3AINDUSTRY%2Cvalues%3AList((id%3A6%2Ctext%3ATechnology%252C%2520Information%2520and%2520Internet%2CselectionType%3AINCLUDED)))"
|
|
149
|
+
"%2C(type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A153%2Ctext%3AChief%2520Technology%2520Officer%2CselectionType%3AINCLUDED)))"
|
|
150
|
+
"%2C(type%3AYEARS_OF_EXPERIENCE%2Cvalues%3AList((id%3A4%2Ctext%3A6%2520to%252010%2520years%2CselectionType%3AINCLUDED)))"
|
|
151
|
+
"%2C(type%3ASCHOOL%2Cvalues%3AList((id%3A1792%2Ctext%3AStanford%2520University%2CselectionType%3AINCLUDED)))"
|
|
152
|
+
"%2C(type%3AFIRST_NAME%2Cvalues%3AList((text%3AJohn%2CselectionType%3AINCLUDED)))%2C(type%3ALAST_NAME%2Cvalues%3A"
|
|
153
|
+
"List((text%3ADoe%2CselectionType%3AINCLUDED)))%2C(type%3AGROUP%2Cvalues%3AList((id%3A5119103%2Ctext%3AMobile%2520Integration%2520Cloud%2520Services%2CselectionType%3AINCLUDED)))))viewAllFilters=true"
|
|
154
|
+
"\n 8. Example of some role related filters you can use like job title, seniority level, years at current company: \n"
|
|
155
|
+
"https://www.linkedin.com/sales/search/people?query=(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)%2Cfilters"
|
|
156
|
+
"%3AList((type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A153%2Ctext%3AChief%2520Technology%2520Officer%2CselectionType%3AINCLUDED)))"
|
|
157
|
+
"%2C(type%3AFUNCTION%2Cvalues%3AList((id%3A8%2Ctext%3AEngineering%2CselectionType%3AINCLUDED)%2C(id%3A25%2Ctext%3ASales%2CselectionType%3AINCLUDED)"
|
|
158
|
+
"%2C(id%3A15%2Ctext%3AMarketing%2CselectionType%3AINCLUDED)))%2C(type%3ASENIORITY_LEVEL%2Cvalues%3AList((id%3A120%2Ctext%3ASenior%2CselectionType%3AINCLUDED)"
|
|
159
|
+
"%2C(id%3A310%2Ctext%3ACXO%2CselectionType%3AINCLUDED)%2C(id%3A110%2Ctext%3AEntry%2520Level%2CselectionType%3AEXCLUDED)))"
|
|
160
|
+
"%2C(type%3APAST_TITLE%2Cvalues%3AList((id%3A5%2Ctext%3ADirector%2CselectionType%3AINCLUDED)))"
|
|
161
|
+
"%2C(type%3AYEARS_AT_CURRENT_COMPANY%2Cvalues%3AList((id%3A3%2Ctext%3A3%2520to%25205%2520years%2CselectionType%3AINCLUDED)))"
|
|
162
|
+
"%2C(type%3AYEARS_IN_CURRENT_POSITION%2Cvalues%3AList((id%3A3%2Ctext%3A3%2520to%25205%2520years%2CselectionType%3AINCLUDED)))))"
|
|
163
|
+
"\n 9. Example of some lead company related filters you can use like company headcount, company name, previous company etc: \n"
|
|
164
|
+
"https://www.linkedin.com/sales/search/people?query=(recentSearchParam%3A(id%3A4395364884%2CdoLogHistory%3Atrue)%2Cfilters%3Ac"
|
|
165
|
+
"List((type%3ACURRENT_TITLE%2Cvalues%3AList((id%3A136%2Ctext%3AVice%2520President%2520of%2520Sales%2CselectionType%3AINCLUDED)))"
|
|
166
|
+
"%2C(type%3ACURRENT_COMPANY%2Cvalues%3AList((id%3Aurn%253Ali%253Aorganization%253A5289249%2Ctext%3AArangoDB%2CselectionType%3AINCLUDED%2Cparent%3A(id%3A0))))"
|
|
167
|
+
"%2C(type%3ACOMPANY_HEADCOUNT%2Cvalues%3AList((id%3AD%2Ctext%3A51-200%2CselectionType%3AINCLUDED)%2C(id%3AC%2Ctext%3A11-50%2CselectionType%3AINCLUDED)))"
|
|
168
|
+
"%2C(type%3APAST_COMPANY%2Cvalues%3AList((id%3Aurn%253Ali%253Aorganization%253A828370%2Ctext%3ANeo4j%2CselectionType%3AINCLUDED%2Cparent%3A(id%3A0))))"
|
|
169
|
+
"%2C(type%3ACOMPANY_TYPE%2Cvalues%3AList((id%3AP%2Ctext%3APrivately%2520Held%2CselectionType%3AINCLUDED)%2C(id%3AC%2Ctext%3APublic%2520Company%2CselectionType%3AINCLUDED)))"
|
|
170
|
+
"%2C(type%3ACOMPANY_HEADQUARTERS%2Cvalues%3AList((id%3A103644278%2Ctext%3AUnited%2520States%2CselectionType%3AINCLUDED)))))"
|
|
171
|
+
"Below is example of using custom keywords to search for people having neo4j in profile: \n"
|
|
172
|
+
"https://www.linkedin.com/sales/search/people?query=(spellCorrectionEnabled%3Atrue%2Ckeywords%3Aneo4j)\n"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# 1. Validate presence of input
|
|
177
|
+
if not english_description and not user_input_salesnav_url:
|
|
178
|
+
raise ValueError("Error: Neither english_description nor user_input_salesnav_url was provided.")
|
|
179
|
+
|
|
180
|
+
# 2. Build the user_prompt conditionally
|
|
181
|
+
if english_description and user_input_salesnav_url:
|
|
182
|
+
# Case 1: Both present
|
|
183
|
+
user_prompt = f"""
|
|
184
|
+
{system_message}
|
|
185
|
+
|
|
186
|
+
The user wants to build a Sales Navigator people-search URL for LinkedIn.
|
|
187
|
+
They have described the desired filters in plain English as follows:
|
|
188
|
+
"{english_description}"
|
|
189
|
+
|
|
190
|
+
Sales navigator URL provided by user:
|
|
191
|
+
{user_input_salesnav_url}
|
|
192
|
+
|
|
193
|
+
The supported filters are described below (for your reference):
|
|
194
|
+
{supported_filters_explanation}
|
|
195
|
+
|
|
196
|
+
Some example URLs:
|
|
197
|
+
{few_examples_of_queries}
|
|
198
|
+
|
|
199
|
+
Do the following step by step:
|
|
200
|
+
1. Think about the filters required to query the leads.
|
|
201
|
+
2. Since the user provided a URL, incorporate or validate that URL.
|
|
202
|
+
3. Look at the examples and supported filters to build the query.
|
|
203
|
+
4. Make sure the URL generated is valid. Don't make up filters not in the list.
|
|
204
|
+
Double-check to ensure the URL is in valid Sales Navigator format with properly-encoded parameters.
|
|
205
|
+
Output MUST be valid JSON with only 'linkedin_salenav_url_with_query_parameters' as a key.
|
|
206
|
+
"""
|
|
207
|
+
elif not english_description and user_input_salesnav_url:
|
|
208
|
+
# Case 2: Only user_input_salesnav_url
|
|
209
|
+
user_prompt = f"""
|
|
210
|
+
{system_message}
|
|
211
|
+
|
|
212
|
+
The user has only provided a Sales Navigator URL to use:
|
|
213
|
+
{user_input_salesnav_url}
|
|
214
|
+
|
|
215
|
+
You do not have an English description of desired filters. Please use or validate
|
|
216
|
+
the provided Sales Navigator URL. The supported filters are described below (for your reference):
|
|
217
|
+
{supported_filters_explanation}
|
|
218
|
+
|
|
219
|
+
Some example URLs:
|
|
220
|
+
{few_examples_of_queries}
|
|
221
|
+
|
|
222
|
+
Output MUST be valid JSON with only 'linkedin_salenav_url_with_query_parameters' as a key.
|
|
223
|
+
"""
|
|
224
|
+
else:
|
|
225
|
+
# Case 3: Only english_description
|
|
226
|
+
user_prompt = f"""
|
|
227
|
+
{system_message}
|
|
228
|
+
|
|
229
|
+
They have described the desired filters in plain English as follows:
|
|
230
|
+
"{english_description}"
|
|
231
|
+
|
|
232
|
+
The supported filters are described below (for your reference):
|
|
233
|
+
{supported_filters_explanation}
|
|
234
|
+
|
|
235
|
+
Some example URLs:
|
|
236
|
+
{few_examples_of_queries}
|
|
237
|
+
|
|
238
|
+
Do the following step by step:
|
|
239
|
+
1. Think about the filters required to query the leads based on the English description.
|
|
240
|
+
2. Look at the examples and supported filters to build the query.
|
|
241
|
+
3. Make sure the URL generated is valid. Don't make up filters not in the list.
|
|
242
|
+
Double-check to ensure the URL is in valid Sales Navigator format with properly-encoded parameters.
|
|
243
|
+
Output MUST be valid JSON with only 'linkedin_salenav_url_with_query_parameters' as a key.
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
logger.info("Generating Sales Navigator people-search URL from description: '%s'", english_description)
|
|
247
|
+
|
|
248
|
+
# 3. Call your structured-output helper
|
|
249
|
+
response, status = await get_structured_output_internal(
|
|
250
|
+
user_prompt,
|
|
251
|
+
SalesNavQuery,
|
|
252
|
+
tool_config=tool_config
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
if status != "SUCCESS" or not response:
|
|
256
|
+
raise Exception("Error generating the Sales Navigator URL.")
|
|
257
|
+
|
|
258
|
+
logger.info("Successfully generated Sales Navigator URL.")
|
|
259
|
+
return response.dict()
|