srilakshu012456 commited on
Commit
14aadef
·
verified ·
1 Parent(s): deb8250

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +23 -66
main.py CHANGED
@@ -12,65 +12,21 @@ from pydantic import BaseModel
12
  from dotenv import load_dotenv
13
  from datetime import datetime
14
 
15
- # ------------------------------ Safe imports for Pylance ------------------------------
16
- # If your editor/Pylance can't resolve the local package, these stubs prevent "unresolved import"
17
- # while you fix your workspace settings (see tips below).
18
- try:
19
- # Import shared vocab from KB services
20
- from services.kb_creation import ACTION_SYNONYMS, MODULE_VOCAB
21
- from services.kb_creation import (
22
- collection,
23
- ingest_documents,
24
- hybrid_search_knowledge_base,
25
- get_section_text,
26
- get_best_steps_section_text,
27
- get_best_errors_section_text,
28
- get_escalation_text, # for escalation heading
29
- )
30
- from services.kb_creation import bm25_docs
31
- from services.login import router as login_router
32
- from services.generate_ticket import get_valid_token, create_incident
33
- except Exception:
34
- # Lightweight fallbacks (only to make Pylance happy; you should use real implementations at runtime)
35
- ACTION_SYNONYMS: Dict[str, List[str]] = {"create": ["create"], "update": ["update"], "delete": ["delete"]}
36
- MODULE_VOCAB: Dict[str, List[str]] = {"appointments": ["appointment", "schedule"]}
37
- bm25_docs: List[Dict[str, Any]] = []
38
-
39
- class _DummyColl:
40
- def count(self) -> int:
41
- return 0
42
-
43
- def collection() -> _DummyColl:
44
- return _DummyColl()
45
-
46
- def ingest_documents(folder_path: str) -> None:
47
- raise NotImplementedError("ingest_documents stub in editor mode")
48
-
49
- def hybrid_search_knowledge_base(q: str, top_k: int = 10, alpha: float = 0.6, beta: float = 0.4) -> Dict[str, Any]:
50
- return {"documents": [], "metadatas": [], "distances": [], "combined_scores": [], "user_intent": "neutral", "best_doc": None, "actions": []}
51
-
52
- def get_section_text(doc: Optional[str], section: Optional[str]) -> str:
53
- return ""
54
-
55
- def get_best_steps_section_text(doc: Optional[str]) -> str:
56
- return ""
57
-
58
- def get_best_errors_section_text(doc: Optional[str]) -> str:
59
- return ""
60
-
61
- def get_escalation_text(doc: Optional[str]) -> str:
62
- return ""
63
-
64
- class _DummyRouter:
65
- pass
66
-
67
- login_router = _DummyRouter()
68
-
69
- def get_valid_token() -> str:
70
- return ""
71
-
72
- def create_incident(short: str, desc: str) -> Dict[str, Any]:
73
- return {"error": "ServiceNow not configured"}
74
 
75
  # ------------------------------ Config ------------------------------
76
  VERIFY_SSL = os.getenv("SERVICENOW_SSL_VERIFY", "true").lower() in ("1", "true", "yes")
@@ -103,10 +59,7 @@ async def lifespan(app: FastAPI):
103
 
104
 
105
  app = FastAPI(lifespan=lifespan)
106
- try:
107
- app.include_router(login_router)
108
- except Exception:
109
- pass # stubbed router in editor-only mode
110
 
111
  origins = ["https://chatbotnova-chatbot-frontend.hf.space"]
112
  app.add_middleware(
@@ -221,6 +174,7 @@ def _detect_error_families(msg: str) -> list:
221
  return fams
222
 
223
 
 
224
  def _get_steps_by_title_keywords_global(keywords: List[str], prefer_doc: Optional[str] = None) -> Tuple[Optional[str], Optional[str], Optional[str]]:
225
  """
226
  Search ALL SOP docs for a 'steps' section whose *section title* contains any of `keywords`.
@@ -261,6 +215,7 @@ def _get_steps_by_title_keywords_global(keywords: List[str], prefer_doc: Optiona
261
  _, best_doc_g, best_sec_g, best_text_g = candidates[0]
262
  return best_doc_g, best_sec_g, best_text_g
263
 
 
264
  # --- Action-targeted steps selector (uses existing KB metadata) ---
265
  def _get_steps_for_action(best_doc: str, actions: list) -> Optional[str]:
266
  """
@@ -324,6 +279,7 @@ def _get_steps_for_action_global(actions: list, prefer_doc: Optional[str] = None
324
  _, best_doc_global, best_text = candidates[0]
325
  return best_doc_global, best_text
326
 
 
327
  # --- Default section picker when query doesn't reveal action ---
328
  def _pick_default_action_section(best_doc: str) -> Optional[str]:
329
  """
@@ -1334,7 +1290,7 @@ async def chat_with_ai(input_data: ChatInput):
1334
  next_step_applied = False
1335
  next_step_info: Dict[str, Any] = {}
1336
 
1337
- # ---------------- Steps branch (fixed indentation) ----------------
1338
  if best_doc and detected_intent == "steps":
1339
  context_preformatted = False
1340
  full_steps = None
@@ -1480,7 +1436,7 @@ async def chat_with_ai(input_data: ChatInput):
1480
  ### Output
1481
  Return ONLY the rewritten guidance."""
1482
  headers = {"Content-Type": "application/json"}
1483
- payload = {"contents": [{"parts": [{"text": enhanced_prompt}]}]}
1484
  bot_text = ""
1485
  http_code = 0
1486
  if use_gemini and GEMINI_API_KEY:
@@ -1577,6 +1533,7 @@ Return ONLY the rewritten guidance."""
1577
  except Exception as e:
1578
  raise HTTPException(status_code=500, detail=safe_str(e))
1579
 
 
1580
  # ------------------------------ Ticket description generation ------------------------------
1581
  @app.post("/generate_ticket_desc")
1582
  async def generate_ticket_desc_ep(input_data: TicketDescInput):
@@ -1591,7 +1548,7 @@ async def generate_ticket_desc_ep(input_data: TicketDescInput):
1591
  "Do not include any extra text, comments, or explanations outside the JSON."
1592
  )
1593
  headers = {"Content-Type": "application/json"}
1594
- payload = {"contents": [{"parts": [{"text": prompt}]}]}
1595
  resp = requests.post(GEMINI_URL, headers=headers, json=payload, timeout=25, verify=GEMINI_SSL_VERIFY)
1596
  try:
1597
  data = resp.json()
 
12
  from dotenv import load_dotenv
13
  from datetime import datetime
14
 
15
+ # ------------------------------ Imports ------------------------------
16
+ # Import shared vocab from KB services
17
+ from services.kb_creation import ACTION_SYNONYMS, MODULE_VOCAB
18
+ from services.kb_creation import (
19
+ collection,
20
+ ingest_documents,
21
+ hybrid_search_knowledge_base,
22
+ get_section_text,
23
+ get_best_steps_section_text,
24
+ get_best_errors_section_text,
25
+ get_escalation_text, # for escalation heading
26
+ bm25_docs,
27
+ )
28
+ from services.login import router as login_router
29
+ from services.generate_ticket import get_valid_token, create_incident
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  # ------------------------------ Config ------------------------------
32
  VERIFY_SSL = os.getenv("SERVICENOW_SSL_VERIFY", "true").lower() in ("1", "true", "yes")
 
59
 
60
 
61
  app = FastAPI(lifespan=lifespan)
62
+ app.include_router(login_router)
 
 
 
63
 
64
  origins = ["https://chatbotnova-chatbot-frontend.hf.space"]
65
  app.add_middleware(
 
174
  return fams
175
 
176
 
177
+ # --- Title keywords global selector (robust when action_tag is missing) ---
178
  def _get_steps_by_title_keywords_global(keywords: List[str], prefer_doc: Optional[str] = None) -> Tuple[Optional[str], Optional[str], Optional[str]]:
179
  """
180
  Search ALL SOP docs for a 'steps' section whose *section title* contains any of `keywords`.
 
215
  _, best_doc_g, best_sec_g, best_text_g = candidates[0]
216
  return best_doc_g, best_sec_g, best_text_g
217
 
218
+
219
  # --- Action-targeted steps selector (uses existing KB metadata) ---
220
  def _get_steps_for_action(best_doc: str, actions: list) -> Optional[str]:
221
  """
 
279
  _, best_doc_global, best_text = candidates[0]
280
  return best_doc_global, best_text
281
 
282
+
283
  # --- Default section picker when query doesn't reveal action ---
284
  def _pick_default_action_section(best_doc: str) -> Optional[str]:
285
  """
 
1290
  next_step_applied = False
1291
  next_step_info: Dict[str, Any] = {}
1292
 
1293
+ # ---------------- Steps branch ----------------
1294
  if best_doc and detected_intent == "steps":
1295
  context_preformatted = False
1296
  full_steps = None
 
1436
  ### Output
1437
  Return ONLY the rewritten guidance."""
1438
  headers = {"Content-Type": "application/json"}
1439
+ payload = {"contents": [{"parts": [{"text": enhanced_prompt}]}]]}
1440
  bot_text = ""
1441
  http_code = 0
1442
  if use_gemini and GEMINI_API_KEY:
 
1533
  except Exception as e:
1534
  raise HTTPException(status_code=500, detail=safe_str(e))
1535
 
1536
+
1537
  # ------------------------------ Ticket description generation ------------------------------
1538
  @app.post("/generate_ticket_desc")
1539
  async def generate_ticket_desc_ep(input_data: TicketDescInput):
 
1548
  "Do not include any extra text, comments, or explanations outside the JSON."
1549
  )
1550
  headers = {"Content-Type": "application/json"}
1551
+ payload = {"contents": [{"parts": [{"text": prompt}]}]]}
1552
  resp = requests.post(GEMINI_URL, headers=headers, json=payload, timeout=25, verify=GEMINI_SSL_VERIFY)
1553
  try:
1554
  data = resp.json()