rakib72642 commited on
Commit
a6fa796
ยท
1 Parent(s): 42c497a

updated mail

Browse files
Files changed (2) hide show
  1. core/backend.py +304 -19
  2. services/tts.py +1 -1
core/backend.py CHANGED
@@ -305,8 +305,16 @@ async def send_mail(to_mail: str, subject: str, body: str):
305
  email["From"] = smtp_user
306
  email["To"] = to_mail
307
  email["Subject"] = subject
 
308
  email.set_content(body)
309
 
 
 
 
 
 
 
 
310
  await aiosmtplib.send(
311
  email,
312
  hostname="smtp.gmail.com",
@@ -316,6 +324,73 @@ async def send_mail(to_mail: str, subject: str, body: str):
316
  use_tls=True,
317
  )
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
320
  # TOOLS
321
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
@@ -735,14 +810,198 @@ async def book_appointment(
735
 
736
 
737
  @tool
738
- async def delete_appointment(patient_num: str, doctor_name: str = "", doctor_id: int = 0) -> str:
739
- """Delete an appointment using the patient's phone number and doctor name or ID."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
  db_path = get_db_path()
741
  patient_num = format_bd_number(patient_num)
742
  doctor_name = _clean_text(doctor_name)
 
743
 
744
  async with aiosqlite.connect(db_path) as db:
745
  db.row_factory = aiosqlite.Row
 
746
 
747
  if not doctor_name and doctor_id:
748
  cursor = await db.execute("SELECT doctor_name FROM doctors WHERE id = ?", (doctor_id,))
@@ -756,16 +1015,9 @@ async def delete_appointment(patient_num: str, doctor_name: str = "", doctor_id:
756
  WHERE patient_num = ? AND LOWER(doctor_name) = LOWER(?)""",
757
  (patient_num, doctor_name),
758
  )
759
- row = await cursor.fetchone()
760
- if not row:
761
  return json.dumps({"success": False, "message": "No matching appointment found."})
762
-
763
- await db.execute(
764
- """DELETE FROM patients
765
- WHERE patient_num = ? AND LOWER(doctor_name) = LOWER(?)""",
766
- (patient_num, doctor_name),
767
- )
768
- await db.commit()
769
  else:
770
  cursor = await db.execute(
771
  """SELECT * FROM patients
@@ -784,17 +1036,46 @@ async def delete_appointment(patient_num: str, doctor_name: str = "", doctor_id:
784
  "data": [dict(row) for row in rows],
785
  }, ensure_ascii=False)
786
 
787
- await db.execute(
788
- """DELETE FROM patients
789
- WHERE id = ?""",
790
- (rows[0]["id"],),
791
- )
792
- await db.commit()
793
- doctor_name = rows[0]["doctor_name"] or doctor_name
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
794
 
795
  return json.dumps({
796
  "success": True,
797
- "message": f"Appointment with Dr. {doctor_name} deleted successfully.",
798
  }, ensure_ascii=False)
799
 
800
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
@@ -844,6 +1125,7 @@ TOOL RULES:
844
  - Use `find_doctors` first for doctor search, specialty search, and availability search.
845
  - Use `get_doctors_by_day` or `get_categories_by_day` when the user asks about a day directly.
846
  - Use `book_appointment` only after identifying the doctor and required patient details.
 
847
  - Never invent `doctor_id`. Get it from tool results or resolve by doctor_name/category.
848
  - If the user gives a Bangla date like "เฆ†เฆ—เฆพเฆฎเง€เฆ•เฆพเฆฒ" or "เฆชเฆฐเฆถเง", convert it to a real date before booking.
849
  - Email is REQUIRED for booking and must be used to send a confirmation mail.
@@ -882,6 +1164,7 @@ You must now choose the correct tool instead of answering in prose:
882
  - Use `find_doctors` or `search_doctor` for doctor/specialty/availability questions.
883
  - Use `get_doctors_by_day` or `get_categories_by_day` for day-based availability.
884
  - Use `book_appointment` when the user is confirming a booking.
 
885
  - Use `delete_appointment` when the user is cancelling a booking.
886
 
887
  Important booking rules:
@@ -893,6 +1176,7 @@ Important booking rules:
893
  Important cancellation rules:
894
  - If the user gave only a phone number and there is exactly one matching appointment, cancel it directly.
895
  - If multiple appointments match, ask only for the doctor name.
 
896
 
897
  Do not give a normal conversational answer before the tool call.
898
  """
@@ -927,6 +1211,7 @@ class AIBackend:
927
  book_appointment,
928
  get_bd_time,
929
  search_appointment_by_phone,
 
930
  delete_appointment,
931
  get_categories_by_day,
932
  get_doctors_by_day
 
305
  email["From"] = smtp_user
306
  email["To"] = to_mail
307
  email["Subject"] = subject
308
+ # Plain-text fallback
309
  email.set_content(body)
310
 
311
+ # Professional HTML version
312
+ try:
313
+ html = _format_email_html(subject=subject, body_text=body)
314
+ email.add_alternative(html, subtype="html")
315
+ except Exception:
316
+ pass
317
+
318
  await aiosmtplib.send(
319
  email,
320
  hostname="smtp.gmail.com",
 
324
  use_tls=True,
325
  )
326
 
327
+
328
+ def _format_email_html(subject: str, body_text: str) -> str:
329
+ """
330
+ Render a simple, professional HTML email.
331
+ Input body_text should be plain text with newlines.
332
+ """
333
+ safe = (
334
+ (body_text or "")
335
+ .replace("&", "&")
336
+ .replace("<", "&lt;")
337
+ .replace(">", "&gt;")
338
+ )
339
+ safe = safe.replace("\n", "<br>")
340
+ return f"""\
341
+ <!doctype html>
342
+ <html>
343
+ <body style="margin:0;padding:0;background:#f6f7fb;font-family:Arial,Helvetica,sans-serif;">
344
+ <div style="max-width:640px;margin:0 auto;padding:24px;">
345
+ <div style="background:#ffffff;border-radius:14px;border:1px solid #e6e8f0;overflow:hidden;">
346
+ <div style="padding:18px 20px;background:linear-gradient(135deg,#0ea5e9,#8b5cf6);color:#fff;">
347
+ <div style="font-size:16px;font-weight:700;">{subject}</div>
348
+ <div style="font-size:12px;opacity:.9;margin-top:4px;">Aasha โ€ข Hospital Assistant</div>
349
+ </div>
350
+ <div style="padding:18px 20px;color:#0f172a;font-size:14px;line-height:1.55;">
351
+ {safe}
352
+ <div style="margin-top:18px;color:#64748b;font-size:12px;">
353
+ This is an automated message. If you did not request this, please ignore it.
354
+ </div>
355
+ </div>
356
+ </div>
357
+ </div>
358
+ </body>
359
+ </html>
360
+ """
361
+
362
+
363
+ def _format_appt_email_text(
364
+ action: str,
365
+ doctor_name: str,
366
+ patient_name: str,
367
+ patient_num: str,
368
+ visiting_date: str,
369
+ visiting_day: str,
370
+ visiting_time: str,
371
+ extra: str = "",
372
+ ) -> str:
373
+ action_line = {
374
+ "booked": "โœ… Appointment Confirmed",
375
+ "updated": "โœ… Appointment Updated",
376
+ "cancelled": "โœ… Appointment Cancelled",
377
+ }.get(action, "โœ… Appointment Update")
378
+
379
+ lines = [
380
+ action_line,
381
+ "",
382
+ f"Doctor : {doctor_name}",
383
+ f"Patient : {patient_name}",
384
+ f"Contact : {patient_num}",
385
+ f"Visit Date : {visiting_date}",
386
+ f"Visit Day : {visiting_day}",
387
+ f"Visit Time : {visiting_time}",
388
+ ]
389
+ if extra:
390
+ lines.extend(["", extra.strip()])
391
+ lines.extend(["", "Thank you.", "Aasha โ€ข Hospital Assistant"])
392
+ return "\n".join(lines)
393
+
394
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
395
  # TOOLS
396
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
 
810
 
811
 
812
  @tool
813
+ async def update_appointment(
814
+ patient_num: str,
815
+ doctor_name: str = "",
816
+ doctor_id: int = 0,
817
+ new_visiting_date: str = "",
818
+ new_doctor_name: str = "",
819
+ new_patient_num: str = "",
820
+ new_patient_mail: str = "",
821
+ ) -> str:
822
+ """
823
+ Update an existing appointment found by phone number.
824
+
825
+ You can update:
826
+ - visit date/day
827
+ - doctor (by name or id)
828
+ - phone number
829
+ - email
830
+
831
+ Rules:
832
+ - patient_num is required for lookup.
833
+ - If multiple appointments exist for the phone number, provide doctor_name
834
+ (or doctor_id) to select which one to update.
835
+ - A confirmation email is REQUIRED for updates: either the existing
836
+ appointment has an email, or provide new_patient_mail.
837
+ """
838
+ db_path = get_db_path()
839
+ patient_num_norm = format_bd_number(patient_num)
840
+ selector_name = _clean_text(doctor_name)
841
+ new_doctor_name = _clean_text(new_doctor_name)
842
+ new_patient_num = format_bd_number(new_patient_num) if new_patient_num else ""
843
+ new_patient_mail = _clean_text(new_patient_mail)
844
+ new_visiting_date = _clean_text(new_visiting_date)
845
+
846
+ parsed_date = _parse_visit_date(new_visiting_date) if new_visiting_date else None
847
+ if parsed_date:
848
+ new_visiting_date = parsed_date
849
+
850
+ if not patient_num_norm:
851
+ return "Missing details. Need patient phone number."
852
+
853
+ if not any([new_visiting_date, new_doctor_name, new_patient_num, new_patient_mail, doctor_id]):
854
+ return "Nothing to update. Provide new date, doctor, phone, or email."
855
+
856
+ async with aiosqlite.connect(db_path) as db:
857
+ db.row_factory = aiosqlite.Row
858
+
859
+ # Find matching appointments
860
+ params = [patient_num_norm]
861
+ q = "SELECT * FROM patients WHERE patient_num = ?"
862
+ if selector_name:
863
+ q += " AND LOWER(doctor_name) = LOWER(?)"
864
+ params.append(selector_name)
865
+ rows = await (await db.execute(q, params)).fetchall()
866
+
867
+ if not rows:
868
+ return "No appointment found for this phone number."
869
+ if len(rows) > 1 and not selector_name:
870
+ return (
871
+ "Multiple appointments found for this phone number. "
872
+ "Please specify the doctor name to update."
873
+ )
874
+
875
+ appt = dict(rows[0])
876
+
877
+ # Resolve new doctor if requested
878
+ resolved_doctor = None
879
+ if doctor_id:
880
+ d = await (await db.execute("SELECT * FROM doctors WHERE id = ?", (doctor_id,))).fetchone()
881
+ if d:
882
+ resolved_doctor = dict(d)
883
+ if resolved_doctor is None and new_doctor_name:
884
+ d = await (await db.execute(
885
+ "SELECT * FROM doctors WHERE LOWER(doctor_name) = LOWER(?)",
886
+ (new_doctor_name,),
887
+ )).fetchone()
888
+ if d:
889
+ resolved_doctor = dict(d)
890
+ else:
891
+ return f"No doctor found with name '{new_doctor_name}'."
892
+
893
+ # Build updated fields
894
+ updated_doctor_name = appt.get("doctor_name", "")
895
+ updated_doctor_category = appt.get("doctor_category", "")
896
+ updated_visiting_time = appt.get("visiting_time", "")
897
+ updated_visiting_day = appt.get("visiting_day", "")
898
+ updated_visiting_date = appt.get("visiting_date", "")
899
+ updated_patient_num = appt.get("patient_num", "")
900
+ updated_patient_mail = appt.get("patient_mail", "")
901
+
902
+ if resolved_doctor:
903
+ updated_doctor_name = resolved_doctor.get("doctor_name", updated_doctor_name)
904
+ updated_doctor_category = resolved_doctor.get("category", updated_doctor_category)
905
+ updated_visiting_time = (resolved_doctor.get("visiting_time") or updated_visiting_time).strip()
906
+ updated_visiting_day = (resolved_doctor.get("visiting_days") or updated_visiting_day).strip()
907
+
908
+ if new_visiting_date:
909
+ updated_visiting_date = new_visiting_date
910
+ # Derive English day name from date for consistency
911
+ try:
912
+ import datetime as _dt
913
+ y, m, d = [int(x) for x in updated_visiting_date.split("-")]
914
+ updated_visiting_day = _dt.date(y, m, d).strftime("%A")
915
+ except Exception:
916
+ pass
917
+
918
+ if new_patient_num:
919
+ updated_patient_num = new_patient_num
920
+ if new_patient_mail:
921
+ updated_patient_mail = new_patient_mail
922
+
923
+ if not updated_patient_mail:
924
+ return "Email is required to update an appointment. Please provide an email address."
925
+
926
+ await db.execute(
927
+ """UPDATE patients
928
+ SET doctor_name = ?,
929
+ doctor_category = ?,
930
+ patient_num = ?,
931
+ visiting_date = ?,
932
+ visiting_day = ?,
933
+ visiting_time = ?,
934
+ patient_mail = ?
935
+ WHERE id = ?""",
936
+ (
937
+ updated_doctor_name,
938
+ updated_doctor_category,
939
+ updated_patient_num,
940
+ updated_visiting_date,
941
+ updated_visiting_day,
942
+ updated_visiting_time,
943
+ updated_patient_mail,
944
+ appt["id"],
945
+ ),
946
+ )
947
+ await db.commit()
948
+
949
+ # Send confirmation email
950
+ patient_name = appt.get("patient_name", "Patient")
951
+ email_text = _format_appt_email_text(
952
+ action="updated",
953
+ doctor_name=updated_doctor_name,
954
+ patient_name=patient_name,
955
+ patient_num=updated_patient_num,
956
+ visiting_date=updated_visiting_date,
957
+ visiting_day=updated_visiting_day,
958
+ visiting_time=updated_visiting_time,
959
+ extra="Your appointment details have been updated successfully.",
960
+ )
961
+ try:
962
+ await send_mail(
963
+ to_mail=updated_patient_mail,
964
+ subject="Appointment Updated",
965
+ body=email_text,
966
+ )
967
+ mail_status = "๐Ÿ“ง Confirmation mail sent."
968
+ except Exception as e:
969
+ mail_status = f"โš ๏ธ Mail failed: {str(e)}"
970
+
971
+ return (
972
+ "โœ… Appointment Updated!\n"
973
+ "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n"
974
+ f"Doctor : {updated_doctor_name}\n"
975
+ f"Patient : {patient_name}\n"
976
+ f"Date : {updated_visiting_date}\n"
977
+ f"Day : {updated_visiting_day}\n"
978
+ f"Time : {updated_visiting_time}\n"
979
+ f"Contact : {updated_patient_num}\n"
980
+ f"Email : {updated_patient_mail}\n"
981
+ "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n"
982
+ f"{mail_status}"
983
+ )
984
+
985
+
986
+ @tool
987
+ async def delete_appointment(
988
+ patient_num: str,
989
+ doctor_name: str = "",
990
+ doctor_id: int = 0,
991
+ patient_mail: str = "",
992
+ ) -> str:
993
+ """
994
+ Cancel (delete) an appointment.
995
+ Sends a confirmation email to the patient (required).
996
+ """
997
  db_path = get_db_path()
998
  patient_num = format_bd_number(patient_num)
999
  doctor_name = _clean_text(doctor_name)
1000
+ patient_mail = _clean_text(patient_mail)
1001
 
1002
  async with aiosqlite.connect(db_path) as db:
1003
  db.row_factory = aiosqlite.Row
1004
+ appt_row = None
1005
 
1006
  if not doctor_name and doctor_id:
1007
  cursor = await db.execute("SELECT doctor_name FROM doctors WHERE id = ?", (doctor_id,))
 
1015
  WHERE patient_num = ? AND LOWER(doctor_name) = LOWER(?)""",
1016
  (patient_num, doctor_name),
1017
  )
1018
+ appt_row = await cursor.fetchone()
1019
+ if not appt_row:
1020
  return json.dumps({"success": False, "message": "No matching appointment found."})
 
 
 
 
 
 
 
1021
  else:
1022
  cursor = await db.execute(
1023
  """SELECT * FROM patients
 
1036
  "data": [dict(row) for row in rows],
1037
  }, ensure_ascii=False)
1038
 
1039
+ appt_row = rows[0]
1040
+ doctor_name = appt_row["doctor_name"] or doctor_name
1041
+
1042
+ # Resolve email (required)
1043
+ appt = dict(appt_row) if appt_row is not None else {}
1044
+ appt_email = _clean_text(appt.get("patient_mail", "")) or patient_mail
1045
+ if not appt_email:
1046
+ return json.dumps({
1047
+ "success": False,
1048
+ "message": "Email is required to cancel an appointment. Please provide the email address.",
1049
+ }, ensure_ascii=False)
1050
+
1051
+ # Delete after we have all details for mail
1052
+ await db.execute("DELETE FROM patients WHERE id = ?", (appt["id"],))
1053
+ await db.commit()
1054
+
1055
+ # Send cancellation email
1056
+ email_text = _format_appt_email_text(
1057
+ action="cancelled",
1058
+ doctor_name=appt.get("doctor_name", doctor_name),
1059
+ patient_name=appt.get("patient_name", "Patient"),
1060
+ patient_num=appt.get("patient_num", patient_num),
1061
+ visiting_date=appt.get("visiting_date", ""),
1062
+ visiting_day=appt.get("visiting_day", ""),
1063
+ visiting_time=appt.get("visiting_time", ""),
1064
+ extra="Your appointment has been cancelled successfully.",
1065
+ )
1066
+ try:
1067
+ await send_mail(
1068
+ to_mail=appt_email,
1069
+ subject="Appointment Cancelled",
1070
+ body=email_text,
1071
+ )
1072
+ mail_status = "Confirmation mail sent."
1073
+ except Exception as e:
1074
+ mail_status = f"Mail failed: {str(e)}"
1075
 
1076
  return json.dumps({
1077
  "success": True,
1078
+ "message": f"Appointment with Dr. {doctor_name} cancelled successfully. {mail_status}",
1079
  }, ensure_ascii=False)
1080
 
1081
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
 
1125
  - Use `find_doctors` first for doctor search, specialty search, and availability search.
1126
  - Use `get_doctors_by_day` or `get_categories_by_day` when the user asks about a day directly.
1127
  - Use `book_appointment` only after identifying the doctor and required patient details.
1128
+ - Use `update_appointment` when the user wants to change an existing appointment.
1129
  - Never invent `doctor_id`. Get it from tool results or resolve by doctor_name/category.
1130
  - If the user gives a Bangla date like "เฆ†เฆ—เฆพเฆฎเง€เฆ•เฆพเฆฒ" or "เฆชเฆฐเฆถเง", convert it to a real date before booking.
1131
  - Email is REQUIRED for booking and must be used to send a confirmation mail.
 
1164
  - Use `find_doctors` or `search_doctor` for doctor/specialty/availability questions.
1165
  - Use `get_doctors_by_day` or `get_categories_by_day` for day-based availability.
1166
  - Use `book_appointment` when the user is confirming a booking.
1167
+ - Use `update_appointment` when the user wants to update an appointment.
1168
  - Use `delete_appointment` when the user is cancelling a booking.
1169
 
1170
  Important booking rules:
 
1176
  Important cancellation rules:
1177
  - If the user gave only a phone number and there is exactly one matching appointment, cancel it directly.
1178
  - If multiple appointments match, ask only for the doctor name.
1179
+ - Email is REQUIRED to cancel or update. If missing, ask for email.
1180
 
1181
  Do not give a normal conversational answer before the tool call.
1182
  """
 
1211
  book_appointment,
1212
  get_bd_time,
1213
  search_appointment_by_phone,
1214
+ update_appointment,
1215
  delete_appointment,
1216
  get_categories_by_day,
1217
  get_doctors_by_day
services/tts.py CHANGED
@@ -44,7 +44,7 @@ def _parse_pct(text: str) -> float:
44
  # - `ELEVENLABS_SPEED_PCT` is an optional relative adjustment like "+10%" or "-5%".
45
  # This is applied on top of the base: effective = base * (1 + pct).
46
  # - The final value is clamped to a safe range to avoid invalid API values.
47
- _ELEVEN_BASE_SPEED = float(os.getenv("ELEVENLABS_SPEED", "3"))
48
  _ELEVEN_SPEED_PCT = _parse_pct(os.getenv("ELEVENLABS_SPEED_PCT", "0%"))
49
  ELEVENLABS_SPEED = _clamp(_ELEVEN_BASE_SPEED * (1.0 + _ELEVEN_SPEED_PCT), 0.5, 2.5)
50
  ELEVENLABS_OUTPUT_FORMAT = "mp3_22050_32"
 
44
  # - `ELEVENLABS_SPEED_PCT` is an optional relative adjustment like "+10%" or "-5%".
45
  # This is applied on top of the base: effective = base * (1 + pct).
46
  # - The final value is clamped to a safe range to avoid invalid API values.
47
+ _ELEVEN_BASE_SPEED = float(os.getenv("ELEVENLABS_SPEED", "5"))
48
  _ELEVEN_SPEED_PCT = _parse_pct(os.getenv("ELEVENLABS_SPEED_PCT", "0%"))
49
  ELEVENLABS_SPEED = _clamp(_ELEVEN_BASE_SPEED * (1.0 + _ELEVEN_SPEED_PCT), 0.5, 2.5)
50
  ELEVENLABS_OUTPUT_FORMAT = "mp3_22050_32"