Skip to content

Commit 83b16c5

Browse files
authored
Merge pull request #42 from ERPGulf/version-2
Add quick start guide link to ChatTab component and in Error Messages
2 parents a6820cd + 5f973ac commit 83b16c5

5 files changed

Lines changed: 70 additions & 83 deletions

File tree

changai/changai/api/v2/text2sql_pipeline_v2.py

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ def _safe_join(base: Path, rel: str) -> Path:
7474
"""
7575
p = (base / rel).resolve()
7676
if base != p and base not in p.parents:
77-
frappe.throw(_("Unsafe path: {0}").format(rel))
77+
frappe.throw(_("Unsafe path: {0}\n"
78+
"Check Quick Start Guide Here 👇:\n {1}").format(rel,CHANGAI_GUIDE_LINK))
7879
return p
7980

8081

@@ -86,11 +87,13 @@ def read_asset(file_name: str, base: str = "assets") -> Any:
8687
"""
8788
file_name = (file_name or "").strip()
8889
if not file_name:
89-
frappe.throw(_("file_name is required"))
90+
frappe.throw(_("file_name is required\n"
91+
"Check Quick Start Guide Here 👇:\n {0}").format(CHANGAI_GUIDE_LINK))
9092

9193
ext = Path(file_name).suffix.lower()
9294
if ext not in _ALLOWED_EXT:
93-
frappe.throw(_("Unsupported file type: {0}").format(ext))
95+
frappe.throw(_("Unsupported file type: {0}\n"
96+
"Check Quick Start Guide Here 👇:\n {1}").format(ext, CHANGAI_GUIDE_LINK))
9497

9598
if base == "assets":
9699
root = _ASSETS_DIR
@@ -99,25 +102,29 @@ def read_asset(file_name: str, base: str = "assets") -> Any:
99102
else:
100103
root = None
101104
if root is None:
102-
frappe.throw(_("Invalid base: {0}").format(base))
105+
frappe.throw(_("Invalid base: {0}\n"
106+
"Check Quick Start Guide Here 👇:\n {1}").format(base, CHANGAI_GUIDE_LINK))
103107

104108
path = _safe_join(root, file_name)
105109

106110
if not path.is_file():
107-
frappe.throw(_("File not found: {0}").format(str(path)))
111+
frappe.throw(_("File not found: {0}\n"
112+
"Check Quick Start Guide Here 👇:\n {1}").format(str(path), CHANGAI_GUIDE_LINK))
108113

109114
content = path.read_text(encoding="utf-8", errors="replace")
110115

111116
if ext == ".json":
112117
try:
113118
return json.loads(content)
114119
except json.JSONDecodeError as e:
115-
frappe.throw(_("Invalid JSON in {0}: {1}").format(str(path), str(e)))
120+
frappe.throw(_("Invalid JSON in {0}: {1}"
121+
"Check Quick Start Guide Here 👇:\n {2}").format(str(path), str(e), CHANGAI_GUIDE_LINK))
116122
if ext == ".yaml" or ext == ".yml":
117123
try:
118124
return yaml.safe_load(content)
119125
except yaml.YAMLError as e:
120-
frappe.throw(_("Invalid YAML in {0}: {1}").format(str(path), str(e)))
126+
frappe.throw(_("Invalid YAML in {0}: {1}"
127+
"Check Quick Start Guide Here 👇:\n {2}").format(str(path), str(e), CHANGAI_GUIDE_LINK))
121128
return content
122129

123130
_VS_TABLE = None
@@ -128,7 +135,11 @@ def read_asset(file_name: str, base: str = "assets") -> Any:
128135
STATUS_200 = 200
129136
_SUB_VS_CACHE = {}
130137
APPLICATION_JSON = "application/json"
131-
EMBEDDING_ENGINE_NONE_MESSG = "Embedding engine is None. Model not loaded."
138+
CHANGAI_GUIDE_LINK="https://app.erpgulf.com/en/articles/chang-ai-quick-start-guide"
139+
EMBEDDING_ENGINE_NONE_MESSG = f"""
140+
Embedding engine is None. Model not loaded.
141+
Check Quick Start Guide Here 👇:
142+
{CHANGAI_GUIDE_LINK}"""
132143
MODEL_ID = "gemini-2.5-flash-lite"
133144
RETRY_LIMIT = 2
134145
BACKEND_SERVER_SETTINGS = "Backend Server Settings"
@@ -187,7 +198,7 @@ def download_model_from_ui():
187198

188199
except Exception as e:
189200
frappe.log_error(frappe.get_traceback(), "Embedding Model Download Failed")
190-
frappe.throw(f"Model download failed: {str(e)}")
201+
frappe.throw(_("Model download failed: {0}\n Check Quick Start Guide Here 👇:\n{1}").format(str(e),CHANGAI_GUIDE_LINK))
191202

192203

193204
def get_embedding_engine():
@@ -200,9 +211,9 @@ def get_embedding_engine():
200211
frappe.throw(
201212
_(
202213
"Go to <b>ChangAI Settings</b> and click <b>'Download Embedding Model'</b>.<br><br>"
203-
"Watch this documentation tutorial for more detail: "
204-
"<a href='{0}' target='_blank'>Click here to watch</a>"
205-
).format("https://your-docs-url-here.com"),
214+
"Check this Quick Start Guide for more detail: "
215+
"<a href='{0}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>"
216+
).format(CHANGAI_GUIDE_LINK),
206217
title=_("Embedding Model Required")
207218
)
208219

@@ -416,7 +427,8 @@ def whoami() -> Dict[str, Any]:
416427
mimetype=APPLICATION_JSON,
417428
)
418429
except ValueError as ve:
419-
frappe.throw(ve)
430+
frappe.throw(_("{0}\n Check Quick Start Guide Here 👇:\n {1}").format(ve,CHANGAI_GUIDE_LINK))
431+
420432

421433

422434
def extract_tables_from_sql(sql: str) -> List[str]:
@@ -480,17 +492,20 @@ def _get_gemini_vertex_config(config):
480492
def _throw_missing_vertex_field(project_id: str, location: str, credentials_json: str) -> None:
481493
if not project_id:
482494
frappe.throw(
483-
_("Gemini Project ID is missing.<br><br>Please go to <b>ChangAI Settings</b> and enter your <b>Gemini Project ID</b>."),
495+
_("Gemini Project ID is missing.<br><br>Please go to <b>ChangAI Settings</b> and enter your <b>Gemini Project ID</b>.<br>"
496+
"Check Quick Start Guide 👇:<br><a href='{0}' target='_blank'>Click here</a>").format(CHANGAI_GUIDE_LINK),
484497
title=_("Missing Gemini Project ID"),
485498
)
486499
if not location:
487500
frappe.throw(
488-
_("Gemini Location is missing.<br><br>Please go to <b>ChangAI Settings</b> and enter your <b>Gemini Location</b>."),
501+
_("Gemini Location is missing.<br><br>Please go to <b>ChangAI Settings</b> and enter your <b>Gemini Location</b>.<br>"
502+
"Check Quick Start Guide 👇:<br><a href='{0}' target='_blank'>Click here</a>").format(CHANGAI_GUIDE_LINK),
489503
title=_("Missing Gemini Location"),
490504
)
491505
if not credentials_json:
492506
frappe.throw(
493-
_("Service Account Credentials are missing.<br><br>Please go to <b>ChangAI Settings</b> and enter your <b>Service Account Credential</b>."),
507+
_("Service Account Credentials are missing.<br><br>Please go to <b>ChangAI Settings</b> and enter your <b>Service Account Credential</b>.<br>"
508+
"Check Quick Start Guide 👇:<br><a href='{0}' target='_blank'>Click here</a>").format(CHANGAI_GUIDE_LINK),
494509
title=_("Missing Service Account Credentials"),
495510
)
496511

@@ -528,8 +543,9 @@ def _get_api_key_client(config):
528543
"<a href='https://aistudio.google.com/app/apikey' target='_blank'>Google AI Studio</a>.<br><br>"
529544
"<b>Option 2 (Vertex AI / Service Account):</b><br>"
530545
"Fill in <b>Gemini Project ID</b>, <b>Gemini Location</b>, "
531-
"and <b>Service Account Credentials</b> in <b>ChangAI Settings</b>."
532-
),
546+
"and <b>Service Account Credentials</b> in <b>ChangAI Settings</b>.<br>"
547+
"ChangAI Quick Start Guide 👇:<br><a href='{0}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>"
548+
).format(CHANGAI_GUIDE_LINK),
533549
title=_("Gemini Authentication Not Configured"),
534550
)
535551

@@ -564,28 +580,35 @@ def _clean_gemini_response_text(text: str) -> str:
564580
def _handle_gemini_api_exception(e: Exception) -> None:
565581
if isinstance(e, google_exceptions.ResourceExhausted):
566582
frappe.throw(
567-
_("Gemini API quota exceeded.<br><br>Please wait and try again or upgrade your plan."),
583+
_("Gemini API quota exceeded.<br><br>Please wait and try again or upgrade your plan.<br>Check Quick Start Guide 👇:<br>"
584+
"<a href='{0}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>").format(CHANGAI_GUIDE_LINK),
568585
title=_("Gemini Quota Exceeded"),
569586
)
570587
if isinstance(e, google_exceptions.Unauthenticated):
571588
frappe.throw(
572-
_("Gemini API key is invalid.<br><br>Please go to <b>ChangAI Settings</b> and enter a valid <b>Gemini API Key</b>."),
589+
_("Gemini API key is invalid.<br><br>Please go to <b>ChangAI Settings</b> and enter a valid <b>Gemini API Key</b>.<br>"
590+
"Check ChangAI Quick Start Guide 👇:<br><a href='{0}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>").format(CHANGAI_GUIDE_LINK),
573591
title=_("Invalid Gemini API Key"),
574592
)
575593
if isinstance(e, google_exceptions.PermissionDenied):
576594
frappe.throw(
577-
_("Gemini API permission denied.<br><br>Please check your API key permissions."),
595+
_("Gemini API permission denied.<br><br>Please check your API key permissions.<br>"
596+
"Check ChangAI Quick Start Guide 👇:<br><a href='{0}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>").format(CHANGAI_GUIDE_LINK),
578597
title=_("Gemini Permission Denied"),
579598
)
580599
if isinstance(e, google_exceptions.InvalidArgument):
581600
frappe.throw(
582-
_("Invalid request to Gemini API: {0}").format(str(e)),
601+
_("Invalid request to Gemini API: {0}<br>"
602+
"Check ChangAI Quick Start Guide 👇:<br>"
603+
"<a href='{1}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>").format(str(e),CHANGAI_GUIDE_LINK),
583604
title=_("Gemini Invalid Request"),
584605
)
585606

586607
frappe.log_error(frappe.get_traceback(), "Gemini API Unexpected Error")
587608
frappe.throw(
588-
_("Gemini API error: {0}").format(str(e)),
609+
_("Gemini API error: {0}<br>"
610+
"Check ChangAI Quick Start Guide 👇:<br>"
611+
"<a href='{1}' target='_blank' rel='noopener noreferrer' style='color: #1e90ff;'>Click here</a>").format(str(e),CHANGAI_GUIDE_LINK),
589612
title=_("Gemini API Error"),
590613
)
591614

@@ -789,13 +812,6 @@ def _parse_rewrite_response(raw: Any, user_qstn: str) -> Tuple[str, bool]:
789812
@traceable(name="rewrite_question", run_type="tool")
790813
def rewrite_question(state: SQLState) -> SQLState:
791814
request_id = state.get("request_id")
792-
793-
# publish_pipeline_update(
794-
# request_id,
795-
# "question_rewrite_start",
796-
# "Rewriting user question"
797-
# )
798-
799815
user_qstn = state.get("question") or ""
800816
session_id = state.get("session_id")
801817

@@ -852,7 +868,8 @@ def get_table_vs():
852868
)
853869

854870
if not os.path.exists(table_vs_path):
855-
frappe.throw(_("FAISS table store not found at {0}").format(table_vs_path))
871+
frappe.throw(_("FAISS table store not found at {0}\n"
872+
"Check Quick Start Guide Here 👇:\n {1}").format(table_vs_path,CHANGAI_GUIDE_LINK))
856873

857874
_VS_TABLE = FAISS.load_local(
858875
table_vs_path,
@@ -876,7 +893,8 @@ def get_table_vs_test():
876893
)
877894

878895
if not os.path.exists(table_vs_path):
879-
frappe.throw(_("FAISS table store not found at {0}").format(table_vs_path))
896+
frappe.throw(_("FAISS table store not found at {0} <br>"
897+
f"Check Quick Start Guide Here 👇:\n {1}").format(table_vs_path,CHANGAI_GUIDE_LINK))
880898

881899
_VS_TABLE = FAISS.load_local(
882900
table_vs_path,
@@ -988,7 +1006,8 @@ def get_full_fields_vs_test():
9881006
)
9891007

9901008
if not os.path.isdir(full_fields_vs_path):
991-
frappe.throw(_("Vector store path not found: {0}").format(full_fields_vs_path))
1009+
frappe.throw(_("Vector store path not found: {0}"
1010+
"Check Quick Start Guide Here 👇:\n {1}").format(full_fields_vs_path, CHANGAI_GUIDE_LINK))
9921011

9931012
_FULL_FIELDS_VS = FAISS.load_local(
9941013
full_fields_vs_path,
@@ -1014,7 +1033,8 @@ def get_full_fields_vs():
10141033
)
10151034

10161035
if not os.path.isdir(full_fields_vs_path):
1017-
frappe.throw(_("Vector store path not found: {0}").format(full_fields_vs_path))
1036+
frappe.throw(_("Vector store path not found: {0} <br>"
1037+
"Check Quick Start Guide Here 👇:\n {1}").format(full_fields_vs_path,CHANGAI_GUIDE_LINK))
10181038

10191039
_FULL_FIELDS_VS = FAISS.load_local(
10201040
full_fields_vs_path,
@@ -1235,7 +1255,8 @@ def get_master_vs():
12351255
)
12361256

12371257
if not os.path.exists(master_vs_path):
1238-
frappe.throw(_("FAISS MASTER store not found at {0}.Please click on Update Master Data button in Training tab in ChangAI Settings").format(master_vs_path))
1258+
frappe.throw(_(f"FAISS MASTER store not found at {0}.Please click on Update Master Data button in Training tab in ChangAI Settings"
1259+
f"Check Quick Start Guide Here 👇:\n {1}").format(master_vs_path, CHANGAI_GUIDE_LINK))
12391260

12401261
_VS_MASTER = FAISS.load_local(
12411262
master_vs_path,
@@ -1576,13 +1597,14 @@ def execute_query(sql: str, doctypes: List[str]) -> Any:
15761597
if not sql:
15771598
return []
15781599
if not str(sql).lower().strip().startswith("select"):
1579-
frappe.throw(_("Only SELECT queries are allowed."))
1600+
frappe.throw(_("Only SELECT queries are allowed."
1601+
"Check Quick Start Guide Here 👇:\n {0}").format(CHANGAI_GUIDE_LINK))
15801602
combined = _build_match_conditions(doctypes)
15811603
if combined:
15821604
sql = _append_conditions(sql, combined)
15831605
return frappe.db.sql(sql, as_dict=True)
15841606
except Exception as e:
1585-
return {"error": f"SQL Execution Failed: {e}"}
1607+
return {"error": f"SQL Execution Failed: {e}\n Check Quick Start Guide Here 👇:\n {CHANGAI_GUIDE_LINK}"}
15861608

15871609

15881610
@frappe.whitelist(allow_guest=False)
@@ -2037,8 +2059,8 @@ def _invoke_pipeline(user_question: str, chat_id: str, request_id: str):
20372059
try:
20382060
return app.invoke(initial_state, config=config), None
20392061
except frappe.exceptions.ValidationError as e:
2040-
clean_msg = re.sub(r'<[^>]+>', '', str(e))
2041-
return None, {"Bot": clean_msg, "error": clean_msg}
2062+
# clean_msg = re.sub(r'<[^>]+>', '', str(e))
2063+
return None, {"Bot": str(e), "error": str(e)}
20422064
except Exception as e:
20432065
frappe.log_error(frappe.get_traceback(), "ChangAI Pipeline Invoke Error")
20442066
return None, {"Bot": "⚠️ An unexpected error occurred. Please try again.", "error": str(e)}

changai/changai/doctype/changai_settings/changai_settings.js

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -144,42 +144,6 @@ frappe.ui.form.on("ChangAI Settings", {
144144
Sync the latest database schema so the AI knows your current doctype structure and fields. Run this after adding or modifying any doctypes.
145145
`,
146146
},
147-
{
148-
fieldname: "replicate_prediction_url",
149-
text: `
150-
Optional - The Replicate API endpoint used to send prediction requests to your deployed model on Replicate. Required for remote inference.
151-
`,
152-
},
153-
{
154-
fieldname: "replicate_deploy_url",
155-
text: `
156-
The Replicate deployment endpoint for your model on Replicate. Used to manage or trigger deployments of your AI model.
157-
`,
158-
},
159-
{
160-
fieldname: "sql_generator_llm_version_id",
161-
text: `
162-
Replicate Version ID of the LLM used to generate SQL queries. This controls which model handles text-to-SQL conversion.
163-
`,
164-
},
165-
{
166-
fieldname: "schema_retriever_version_id",
167-
text: `
168-
Replicate Version ID of the schema retriever model. Used to fetch relevant tables and fields from the database schema.
169-
`,
170-
},
171-
{
172-
fieldname: "replicate_api_token",
173-
text: `
174-
Your Replicate API token for authentication. Required to access deployed models on Replicate.
175-
`,
176-
},
177-
{
178-
fieldname: "entity_retriever_version_id",
179-
text: `
180-
Replicate Version ID of the entity retriever model. Helps detect and match real business values like customer names, items, etc.
181-
`,
182-
},
183147
{
184148
fieldname: "openai_api_key",
185149
text: `

changai/public/dist/changai-chatbot.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)