audex 1.0.7a3__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.
- audex/__init__.py +9 -0
- audex/__main__.py +7 -0
- audex/cli/__init__.py +189 -0
- audex/cli/apis/__init__.py +12 -0
- audex/cli/apis/init/__init__.py +34 -0
- audex/cli/apis/init/gencfg.py +130 -0
- audex/cli/apis/init/setup.py +330 -0
- audex/cli/apis/init/vprgroup.py +125 -0
- audex/cli/apis/serve.py +141 -0
- audex/cli/args.py +356 -0
- audex/cli/exceptions.py +44 -0
- audex/cli/helper/__init__.py +0 -0
- audex/cli/helper/ansi.py +193 -0
- audex/cli/helper/display.py +288 -0
- audex/config/__init__.py +64 -0
- audex/config/core/__init__.py +30 -0
- audex/config/core/app.py +29 -0
- audex/config/core/audio.py +45 -0
- audex/config/core/logging.py +163 -0
- audex/config/core/session.py +11 -0
- audex/config/helper/__init__.py +1 -0
- audex/config/helper/client/__init__.py +1 -0
- audex/config/helper/client/http.py +28 -0
- audex/config/helper/client/websocket.py +21 -0
- audex/config/helper/provider/__init__.py +1 -0
- audex/config/helper/provider/dashscope.py +13 -0
- audex/config/helper/provider/unisound.py +18 -0
- audex/config/helper/provider/xfyun.py +23 -0
- audex/config/infrastructure/__init__.py +31 -0
- audex/config/infrastructure/cache.py +51 -0
- audex/config/infrastructure/database.py +48 -0
- audex/config/infrastructure/recorder.py +32 -0
- audex/config/infrastructure/store.py +19 -0
- audex/config/provider/__init__.py +18 -0
- audex/config/provider/transcription.py +109 -0
- audex/config/provider/vpr.py +99 -0
- audex/container.py +40 -0
- audex/entity/__init__.py +468 -0
- audex/entity/doctor.py +109 -0
- audex/entity/doctor.pyi +51 -0
- audex/entity/fields.py +401 -0
- audex/entity/segment.py +115 -0
- audex/entity/segment.pyi +38 -0
- audex/entity/session.py +133 -0
- audex/entity/session.pyi +47 -0
- audex/entity/utterance.py +142 -0
- audex/entity/utterance.pyi +48 -0
- audex/entity/vp.py +68 -0
- audex/entity/vp.pyi +35 -0
- audex/exceptions.py +157 -0
- audex/filters/__init__.py +692 -0
- audex/filters/generated/__init__.py +21 -0
- audex/filters/generated/doctor.py +987 -0
- audex/filters/generated/segment.py +723 -0
- audex/filters/generated/session.py +978 -0
- audex/filters/generated/utterance.py +939 -0
- audex/filters/generated/vp.py +815 -0
- audex/helper/__init__.py +1 -0
- audex/helper/hash.py +33 -0
- audex/helper/mixin.py +65 -0
- audex/helper/net.py +19 -0
- audex/helper/settings/__init__.py +830 -0
- audex/helper/settings/fields.py +317 -0
- audex/helper/stream.py +153 -0
- audex/injectors/__init__.py +1 -0
- audex/injectors/config.py +12 -0
- audex/injectors/lifespan.py +7 -0
- audex/lib/__init__.py +1 -0
- audex/lib/cache/__init__.py +383 -0
- audex/lib/cache/inmemory.py +513 -0
- audex/lib/database/__init__.py +83 -0
- audex/lib/database/sqlite.py +406 -0
- audex/lib/exporter.py +189 -0
- audex/lib/injectors/__init__.py +1 -0
- audex/lib/injectors/cache.py +25 -0
- audex/lib/injectors/container.py +47 -0
- audex/lib/injectors/exporter.py +26 -0
- audex/lib/injectors/recorder.py +33 -0
- audex/lib/injectors/server.py +17 -0
- audex/lib/injectors/session.py +18 -0
- audex/lib/injectors/sqlite.py +24 -0
- audex/lib/injectors/store.py +13 -0
- audex/lib/injectors/transcription.py +42 -0
- audex/lib/injectors/usb.py +12 -0
- audex/lib/injectors/vpr.py +65 -0
- audex/lib/injectors/wifi.py +7 -0
- audex/lib/recorder.py +844 -0
- audex/lib/repos/__init__.py +149 -0
- audex/lib/repos/container.py +23 -0
- audex/lib/repos/database/__init__.py +1 -0
- audex/lib/repos/database/sqlite.py +672 -0
- audex/lib/repos/decorators.py +74 -0
- audex/lib/repos/doctor.py +286 -0
- audex/lib/repos/segment.py +302 -0
- audex/lib/repos/session.py +285 -0
- audex/lib/repos/tables/__init__.py +70 -0
- audex/lib/repos/tables/doctor.py +137 -0
- audex/lib/repos/tables/segment.py +113 -0
- audex/lib/repos/tables/session.py +140 -0
- audex/lib/repos/tables/utterance.py +131 -0
- audex/lib/repos/tables/vp.py +102 -0
- audex/lib/repos/utterance.py +288 -0
- audex/lib/repos/vp.py +286 -0
- audex/lib/restful.py +251 -0
- audex/lib/server/__init__.py +97 -0
- audex/lib/server/auth.py +98 -0
- audex/lib/server/handlers.py +248 -0
- audex/lib/server/templates/index.html.j2 +226 -0
- audex/lib/server/templates/login.html.j2 +111 -0
- audex/lib/server/templates/static/script.js +68 -0
- audex/lib/server/templates/static/style.css +579 -0
- audex/lib/server/types.py +123 -0
- audex/lib/session.py +503 -0
- audex/lib/store/__init__.py +238 -0
- audex/lib/store/localfile.py +411 -0
- audex/lib/transcription/__init__.py +33 -0
- audex/lib/transcription/dashscope.py +525 -0
- audex/lib/transcription/events.py +62 -0
- audex/lib/usb.py +554 -0
- audex/lib/vpr/__init__.py +38 -0
- audex/lib/vpr/unisound/__init__.py +185 -0
- audex/lib/vpr/unisound/types.py +469 -0
- audex/lib/vpr/xfyun/__init__.py +483 -0
- audex/lib/vpr/xfyun/types.py +679 -0
- audex/lib/websocket/__init__.py +8 -0
- audex/lib/websocket/connection.py +485 -0
- audex/lib/websocket/pool.py +991 -0
- audex/lib/wifi.py +1146 -0
- audex/lifespan.py +75 -0
- audex/service/__init__.py +27 -0
- audex/service/decorators.py +73 -0
- audex/service/doctor/__init__.py +652 -0
- audex/service/doctor/const.py +36 -0
- audex/service/doctor/exceptions.py +96 -0
- audex/service/doctor/types.py +54 -0
- audex/service/export/__init__.py +236 -0
- audex/service/export/const.py +17 -0
- audex/service/export/exceptions.py +34 -0
- audex/service/export/types.py +21 -0
- audex/service/injectors/__init__.py +1 -0
- audex/service/injectors/container.py +53 -0
- audex/service/injectors/doctor.py +34 -0
- audex/service/injectors/export.py +27 -0
- audex/service/injectors/session.py +49 -0
- audex/service/session/__init__.py +754 -0
- audex/service/session/const.py +34 -0
- audex/service/session/exceptions.py +67 -0
- audex/service/session/types.py +91 -0
- audex/types.py +39 -0
- audex/utils.py +287 -0
- audex/valueobj/__init__.py +81 -0
- audex/valueobj/common/__init__.py +1 -0
- audex/valueobj/common/auth.py +84 -0
- audex/valueobj/common/email.py +16 -0
- audex/valueobj/common/ops.py +22 -0
- audex/valueobj/common/phone.py +84 -0
- audex/valueobj/common/version.py +72 -0
- audex/valueobj/session.py +19 -0
- audex/valueobj/utterance.py +15 -0
- audex/view/__init__.py +51 -0
- audex/view/container.py +17 -0
- audex/view/decorators.py +303 -0
- audex/view/pages/__init__.py +1 -0
- audex/view/pages/dashboard/__init__.py +286 -0
- audex/view/pages/dashboard/wifi.py +407 -0
- audex/view/pages/login.py +110 -0
- audex/view/pages/recording.py +348 -0
- audex/view/pages/register.py +202 -0
- audex/view/pages/sessions/__init__.py +196 -0
- audex/view/pages/sessions/details.py +224 -0
- audex/view/pages/sessions/export.py +443 -0
- audex/view/pages/settings.py +374 -0
- audex/view/pages/voiceprint/__init__.py +1 -0
- audex/view/pages/voiceprint/enroll.py +195 -0
- audex/view/pages/voiceprint/update.py +195 -0
- audex/view/static/css/dashboard.css +452 -0
- audex/view/static/css/glass.css +22 -0
- audex/view/static/css/global.css +541 -0
- audex/view/static/css/login.css +386 -0
- audex/view/static/css/recording.css +439 -0
- audex/view/static/css/register.css +293 -0
- audex/view/static/css/sessions/styles.css +501 -0
- audex/view/static/css/settings.css +186 -0
- audex/view/static/css/voiceprint/enroll.css +43 -0
- audex/view/static/css/voiceprint/styles.css +209 -0
- audex/view/static/css/voiceprint/update.css +44 -0
- audex/view/static/images/logo.svg +95 -0
- audex/view/static/js/recording.js +42 -0
- audex-1.0.7a3.dist-info/METADATA +361 -0
- audex-1.0.7a3.dist-info/RECORD +192 -0
- audex-1.0.7a3.dist-info/WHEEL +4 -0
- audex-1.0.7a3.dist-info/entry_points.txt +3 -0
audex/entity/session.pyi
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# This file is auto-generated by PrototypeX stub generator.
|
|
2
|
+
# Do not edit manually - changes will be overwritten.
|
|
3
|
+
# Regenerate using: python -m scripts.genstubs gen
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
|
|
9
|
+
from audex.entity import BaseEntity
|
|
10
|
+
from audex.valueobj.session import SessionStatus
|
|
11
|
+
|
|
12
|
+
class Session(BaseEntity):
|
|
13
|
+
id: str
|
|
14
|
+
created_at: datetime.datetime
|
|
15
|
+
updated_at: datetime.datetime | None
|
|
16
|
+
doctor_id: str
|
|
17
|
+
patient_name: str | None
|
|
18
|
+
clinic_number: str | None
|
|
19
|
+
medical_record_number: str | None
|
|
20
|
+
diagnosis: str | None
|
|
21
|
+
status: SessionStatus
|
|
22
|
+
started_at: datetime.datetime | None
|
|
23
|
+
ended_at: datetime.datetime | None
|
|
24
|
+
notes: str | None
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
id: str = ...,
|
|
29
|
+
created_at: datetime.datetime = ...,
|
|
30
|
+
updated_at: datetime.datetime | None = None,
|
|
31
|
+
doctor_id: str,
|
|
32
|
+
patient_name: str | None = None,
|
|
33
|
+
clinic_number: str | None = None,
|
|
34
|
+
medical_record_number: str | None = None,
|
|
35
|
+
diagnosis: str | None = None,
|
|
36
|
+
status: SessionStatus = ...,
|
|
37
|
+
started_at: datetime.datetime | None = None,
|
|
38
|
+
ended_at: datetime.datetime | None = None,
|
|
39
|
+
notes: str | None = None,
|
|
40
|
+
) -> None: ...
|
|
41
|
+
@property
|
|
42
|
+
def is_active(self) -> bool: ...
|
|
43
|
+
@property
|
|
44
|
+
def is_finished(self) -> bool: ...
|
|
45
|
+
def cancel(self) -> None: ...
|
|
46
|
+
def complete(self) -> None: ...
|
|
47
|
+
def start(self) -> None: ...
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
|
|
5
|
+
from audex import utils
|
|
6
|
+
from audex.entity import BaseEntity
|
|
7
|
+
from audex.entity import touch_after
|
|
8
|
+
from audex.entity.fields import DateTimeField
|
|
9
|
+
from audex.entity.fields import FloatField
|
|
10
|
+
from audex.entity.fields import IntegerField
|
|
11
|
+
from audex.entity.fields import StringBackedField
|
|
12
|
+
from audex.entity.fields import StringField
|
|
13
|
+
from audex.valueobj.utterance import Speaker
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Utterance(BaseEntity):
|
|
17
|
+
"""Utterance entity representing a single speech utterance in
|
|
18
|
+
conversation.
|
|
19
|
+
|
|
20
|
+
Represents one continuous speech segment from either the doctor or patient,
|
|
21
|
+
as recognized by ASR (Automatic Speech Recognition) and speaker verification.
|
|
22
|
+
Each utterance contains the transcribed text, speaker identification,
|
|
23
|
+
timing information, and confidence scores.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
id: The unique identifier of the utterance. Auto-generated with
|
|
27
|
+
"utterance-" prefix.
|
|
28
|
+
session_id: The ID of the session this utterance belongs to. Foreign
|
|
29
|
+
key reference to Session entity.
|
|
30
|
+
segment_id: The ID of the audio segment containing this utterance.
|
|
31
|
+
Foreign key reference to Segment entity.
|
|
32
|
+
sequence: The sequence number of this utterance within the session.
|
|
33
|
+
Starts from 1 and increments for each new utterance.
|
|
34
|
+
speaker: The identified speaker (DOCTOR or PATIENT). Determined by
|
|
35
|
+
voiceprint verification against doctor's registered voiceprint.
|
|
36
|
+
text: The transcribed text content from ASR.
|
|
37
|
+
confidence: ASR confidence score, typically between 0.0 and 1.0.
|
|
38
|
+
Higher values indicate more confident transcription.
|
|
39
|
+
start_time_ms: Start time of the utterance within the audio segment,
|
|
40
|
+
in milliseconds from segment start.
|
|
41
|
+
end_time_ms: End time of the utterance within the audio segment,
|
|
42
|
+
in milliseconds from segment start.
|
|
43
|
+
timestamp: Absolute timestamp when the utterance occurred in the
|
|
44
|
+
session timeline.
|
|
45
|
+
|
|
46
|
+
Inherited Attributes:
|
|
47
|
+
created_at: Timestamp when the utterance was created.
|
|
48
|
+
updated_at: Timestamp when the utterance was last updated.
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
```python
|
|
52
|
+
# Create doctor utterance
|
|
53
|
+
utterance = Utterance(
|
|
54
|
+
session_id="session-xyz789",
|
|
55
|
+
segment_id="segment-abc123",
|
|
56
|
+
sequence=1,
|
|
57
|
+
speaker=Speaker.DOCTOR,
|
|
58
|
+
text="您好,今天哪里不舒服?",
|
|
59
|
+
confidence=0.95,
|
|
60
|
+
start_time_ms=1000,
|
|
61
|
+
end_time_ms=3500,
|
|
62
|
+
timestamp=utils.utcnow(),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Create patient utterance
|
|
66
|
+
utterance2 = Utterance(
|
|
67
|
+
session_id="session-xyz789",
|
|
68
|
+
segment_id="segment-abc123",
|
|
69
|
+
sequence=2,
|
|
70
|
+
speaker=Speaker.PATIENT,
|
|
71
|
+
text="医生,我最近总是头疼。",
|
|
72
|
+
confidence=0.88,
|
|
73
|
+
start_time_ms=4000,
|
|
74
|
+
end_time_ms=6800,
|
|
75
|
+
timestamp=utils.utcnow(),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Check speaker
|
|
79
|
+
if utterance.is_doctor:
|
|
80
|
+
print("This is doctor speaking")
|
|
81
|
+
if utterance2.is_patient:
|
|
82
|
+
print("This is patient speaking")
|
|
83
|
+
```
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
id: str = StringField(default_factory=lambda: utils.gen_id(prefix="utterance-"))
|
|
87
|
+
session_id: str = StringField()
|
|
88
|
+
segment_id: str = StringField()
|
|
89
|
+
sequence: int = IntegerField()
|
|
90
|
+
speaker: Speaker = StringBackedField(Speaker)
|
|
91
|
+
text: str = StringField()
|
|
92
|
+
confidence: float | None = FloatField(nullable=True)
|
|
93
|
+
start_time_ms: int = IntegerField()
|
|
94
|
+
end_time_ms: int = IntegerField()
|
|
95
|
+
timestamp: datetime.datetime = DateTimeField(default_factory=utils.utcnow)
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def duration_ms(self) -> int:
|
|
99
|
+
"""Calculate the duration of this utterance in milliseconds.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Duration in milliseconds.
|
|
103
|
+
"""
|
|
104
|
+
return self.end_time_ms - self.start_time_ms
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def is_doctor(self) -> bool:
|
|
108
|
+
"""Check if the speaker is the doctor.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
True if speaker is DOCTOR, False otherwise.
|
|
112
|
+
"""
|
|
113
|
+
return self.speaker == Speaker.DOCTOR
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def is_patient(self) -> bool:
|
|
117
|
+
"""Check if the speaker is the patient.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if speaker is PATIENT, False otherwise.
|
|
121
|
+
"""
|
|
122
|
+
return self.speaker == Speaker.PATIENT
|
|
123
|
+
|
|
124
|
+
@touch_after
|
|
125
|
+
def incr(self) -> None:
|
|
126
|
+
"""Increment the sequence number of this utterance by 1.
|
|
127
|
+
|
|
128
|
+
Note:
|
|
129
|
+
The updated_at timestamp is automatically updated.
|
|
130
|
+
"""
|
|
131
|
+
self.sequence += 1
|
|
132
|
+
|
|
133
|
+
@touch_after
|
|
134
|
+
def decr(self) -> None:
|
|
135
|
+
"""Decrement the sequence number of this utterance by 1.
|
|
136
|
+
|
|
137
|
+
Note:
|
|
138
|
+
The updated_at timestamp is automatically updated.
|
|
139
|
+
"""
|
|
140
|
+
if self.sequence > 1:
|
|
141
|
+
self.sequence -= 1
|
|
142
|
+
raise ValueError("Sequence number cannot be less than 1.")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# This file is auto-generated by PrototypeX stub generator.
|
|
2
|
+
# Do not edit manually - changes will be overwritten.
|
|
3
|
+
# Regenerate using: python -m scripts.genstubs gen
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
|
|
9
|
+
from audex.entity import BaseEntity
|
|
10
|
+
from audex.valueobj.utterance import Speaker
|
|
11
|
+
|
|
12
|
+
class Utterance(BaseEntity):
|
|
13
|
+
id: str
|
|
14
|
+
created_at: datetime.datetime
|
|
15
|
+
updated_at: datetime.datetime | None
|
|
16
|
+
session_id: str
|
|
17
|
+
segment_id: str
|
|
18
|
+
sequence: int
|
|
19
|
+
speaker: Speaker
|
|
20
|
+
text: str
|
|
21
|
+
confidence: float | None
|
|
22
|
+
start_time_ms: int
|
|
23
|
+
end_time_ms: int
|
|
24
|
+
timestamp: datetime.datetime
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
id: str = ...,
|
|
29
|
+
created_at: datetime.datetime = ...,
|
|
30
|
+
updated_at: datetime.datetime | None = None,
|
|
31
|
+
session_id: str,
|
|
32
|
+
segment_id: str,
|
|
33
|
+
sequence: int,
|
|
34
|
+
speaker: Speaker,
|
|
35
|
+
text: str,
|
|
36
|
+
confidence: float | None = None,
|
|
37
|
+
start_time_ms: int,
|
|
38
|
+
end_time_ms: int,
|
|
39
|
+
timestamp: datetime.datetime = ...,
|
|
40
|
+
) -> None: ...
|
|
41
|
+
@property
|
|
42
|
+
def duration_ms(self) -> int: ...
|
|
43
|
+
@property
|
|
44
|
+
def is_doctor(self) -> bool: ...
|
|
45
|
+
@property
|
|
46
|
+
def is_patient(self) -> bool: ...
|
|
47
|
+
def decr(self) -> None: ...
|
|
48
|
+
def incr(self) -> None: ...
|
audex/entity/vp.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from audex import utils
|
|
4
|
+
from audex.entity import BaseEntity
|
|
5
|
+
from audex.entity.fields import BoolField
|
|
6
|
+
from audex.entity.fields import IntegerField
|
|
7
|
+
from audex.entity.fields import StringField
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class VP(BaseEntity):
|
|
11
|
+
"""Voiceprint registration record entity.
|
|
12
|
+
|
|
13
|
+
Represents a voiceprint registration in the VPR system. Links a doctor
|
|
14
|
+
to their registered voiceprint in the external VPR service, storing
|
|
15
|
+
both the local audio reference and remote VPR identifiers.
|
|
16
|
+
|
|
17
|
+
This entity allows for VPR system migration without requiring doctors
|
|
18
|
+
to re-register their voiceprints - the local audio can be re-uploaded
|
|
19
|
+
to a new VPR system.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
id: The unique identifier of the registration. Auto-generated with
|
|
23
|
+
"vp_reg-" prefix.
|
|
24
|
+
doctor_id: The ID of the doctor who owns this voiceprint. Foreign
|
|
25
|
+
key reference to Doctor entity.
|
|
26
|
+
vpr_uid: The unique identifier in the VPR system for this voiceprint.
|
|
27
|
+
Used for 1:1 speaker verification.
|
|
28
|
+
vpr_group_id: The group ID in the VPR system. Optional for organizing
|
|
29
|
+
voiceprints (e.g., by hospital or department).
|
|
30
|
+
audio_key: Local storage key for the voiceprint audio file. Preserved
|
|
31
|
+
for potential re-registration with different VPR systems.
|
|
32
|
+
text_content: The text that was read during voiceprint registration.
|
|
33
|
+
Stored for potential re-registration requirements.
|
|
34
|
+
sample_rate: Audio sample rate used for registration (8000 or 16000 Hz).
|
|
35
|
+
is_active: Whether this registration is currently active. Only one
|
|
36
|
+
active registration per doctor should exist.
|
|
37
|
+
|
|
38
|
+
Inherited Attributes:
|
|
39
|
+
created_at: Timestamp when the registration was created.
|
|
40
|
+
updated_at: Timestamp when the registration was last updated.
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
```python
|
|
44
|
+
# Create voiceprint registration after VPR API call
|
|
45
|
+
registration = VPRegistration(
|
|
46
|
+
doctor_id="doctor-abc123",
|
|
47
|
+
vpr_uid="vpr_user_xyz789",
|
|
48
|
+
vpr_group_id="hospital_001",
|
|
49
|
+
audio_key="vp/doctor-abc123/registration.wav",
|
|
50
|
+
text_content="请朗读以下文本进行声纹注册...",
|
|
51
|
+
sample_rate=16000,
|
|
52
|
+
is_active=True,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Check if active
|
|
56
|
+
if registration.is_active:
|
|
57
|
+
print(f"Active VPR UID: {registration.vpr_uid}")
|
|
58
|
+
```
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
id: str = StringField(default_factory=lambda: utils.gen_id(prefix="vp_reg-"))
|
|
62
|
+
doctor_id: str = StringField()
|
|
63
|
+
vpr_uid: str = StringField()
|
|
64
|
+
vpr_group_id: str = StringField()
|
|
65
|
+
audio_key: str = StringField()
|
|
66
|
+
text_content: str = StringField()
|
|
67
|
+
sample_rate: int = IntegerField()
|
|
68
|
+
is_active: bool = BoolField(default=True)
|
audex/entity/vp.pyi
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# This file is auto-generated by PrototypeX stub generator.
|
|
2
|
+
# Do not edit manually - changes will be overwritten.
|
|
3
|
+
# Regenerate using: python -m scripts.genstubs gen
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
|
|
9
|
+
from audex.entity import BaseEntity
|
|
10
|
+
|
|
11
|
+
class VP(BaseEntity):
|
|
12
|
+
id: str
|
|
13
|
+
created_at: datetime.datetime
|
|
14
|
+
updated_at: datetime.datetime | None
|
|
15
|
+
doctor_id: str
|
|
16
|
+
vpr_uid: str
|
|
17
|
+
vpr_group_id: str
|
|
18
|
+
audio_key: str
|
|
19
|
+
text_content: str
|
|
20
|
+
sample_rate: int
|
|
21
|
+
is_active: bool
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
*,
|
|
25
|
+
id: str = ...,
|
|
26
|
+
created_at: datetime.datetime = ...,
|
|
27
|
+
updated_at: datetime.datetime | None = None,
|
|
28
|
+
doctor_id: str,
|
|
29
|
+
vpr_uid: str,
|
|
30
|
+
vpr_group_id: str,
|
|
31
|
+
audio_key: str,
|
|
32
|
+
text_content: str,
|
|
33
|
+
sample_rate: int,
|
|
34
|
+
is_active: bool = True,
|
|
35
|
+
) -> None: ...
|
audex/exceptions.py
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
|
|
5
|
+
import pydantic as pyd
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AudexError(Exception):
|
|
9
|
+
"""Base exception for all Audex-related errors.
|
|
10
|
+
|
|
11
|
+
Attributes:
|
|
12
|
+
default_message: Default error message for this exception type.
|
|
13
|
+
code: Unique error code identifying this exception type.
|
|
14
|
+
message: The actual error message for this instance.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__slots__ = ("message",)
|
|
18
|
+
|
|
19
|
+
default_message: t.ClassVar[str] = "An error occurred in Audex."
|
|
20
|
+
code: t.ClassVar[int] = 0x01
|
|
21
|
+
|
|
22
|
+
def __init__(self, message: str | None = None) -> None:
|
|
23
|
+
"""Initialize the exception.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
message: Custom error message. If None, uses default_message.
|
|
27
|
+
"""
|
|
28
|
+
self.message = message or self.default_message
|
|
29
|
+
super().__init__(self.message)
|
|
30
|
+
|
|
31
|
+
def __str__(self) -> str:
|
|
32
|
+
"""Return formatted error string with code."""
|
|
33
|
+
return f"[Error {self.code}] {self.message}"
|
|
34
|
+
|
|
35
|
+
def __repr__(self) -> str:
|
|
36
|
+
"""Return detailed representation of the exception."""
|
|
37
|
+
return f"{self.__class__.__name__}(code={self.code}, message={self.message!r})"
|
|
38
|
+
|
|
39
|
+
def as_dict(self) -> dict[str, t.Any]:
|
|
40
|
+
"""Convert exception to dictionary with all slots."""
|
|
41
|
+
data: dict[str, t.Any] = {}
|
|
42
|
+
for slot in getattr(self, "__slots__", []):
|
|
43
|
+
data[slot] = getattr(self, slot, None)
|
|
44
|
+
return data
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class InternalError(AudexError):
|
|
48
|
+
"""Base exception for internal system errors.
|
|
49
|
+
|
|
50
|
+
These errors should NOT expose technical details to users. Frontend
|
|
51
|
+
should display a generic error message and ask users to contact
|
|
52
|
+
support with the error code.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
__slots__ = ("details", "message")
|
|
56
|
+
|
|
57
|
+
default_message = "Internal system error occurred"
|
|
58
|
+
code: t.ClassVar[int] = 0x10
|
|
59
|
+
|
|
60
|
+
def __init__(self, message: str | None = None, **details: t.Any) -> None:
|
|
61
|
+
"""Initialize the exception.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
message: Custom error message. If None, uses default_message.
|
|
65
|
+
**details: Additional technical details for logging/debugging.
|
|
66
|
+
"""
|
|
67
|
+
self.details = details
|
|
68
|
+
full_message = message or self.default_message
|
|
69
|
+
super().__init__(full_message)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class RequiredModuleNotFoundError(InternalError):
|
|
73
|
+
"""Exception raised when a required module is not found."""
|
|
74
|
+
|
|
75
|
+
__slots__ = ("details", "message", "module_name")
|
|
76
|
+
|
|
77
|
+
default_message = "Required module not found"
|
|
78
|
+
code: t.ClassVar[int] = 0x11
|
|
79
|
+
|
|
80
|
+
def __init__(self, *module_name: str, message: str | None = None, **details: t.Any) -> None:
|
|
81
|
+
"""Initialize the exception.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
*module_name: One or more names of missing modules.
|
|
85
|
+
message: Custom error message. If None, uses formatted
|
|
86
|
+
default_message.
|
|
87
|
+
**details: Additional technical details for logging/debugging.
|
|
88
|
+
"""
|
|
89
|
+
self.module_name = module_name
|
|
90
|
+
full_message = message or f"{self.default_message}: {', '.join(module_name)}"
|
|
91
|
+
super().__init__(full_message, **details)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ConfigurationError(InternalError):
|
|
95
|
+
"""Exception raised for configuration errors."""
|
|
96
|
+
|
|
97
|
+
__slots__ = ("config_key", "details", "message")
|
|
98
|
+
|
|
99
|
+
default_message = "Configuration error occurred"
|
|
100
|
+
code: t.ClassVar[int] = 0x13
|
|
101
|
+
|
|
102
|
+
def __init__(
|
|
103
|
+
self, message: str | None = None, *, config_key: str, reason: str, **details: t.Any
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Initialize the exception.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
message: Custom error message. If None, uses formatted
|
|
109
|
+
default_message.
|
|
110
|
+
config_key: The configuration key that caused the error.
|
|
111
|
+
reason: Description of the configuration error.
|
|
112
|
+
**details: Additional technical details for logging/debugging.
|
|
113
|
+
"""
|
|
114
|
+
self.config_key = config_key
|
|
115
|
+
self.reason = reason
|
|
116
|
+
full_message = message or f"{self.default_message}: [{config_key}] {reason}"
|
|
117
|
+
super().__init__(full_message, **details)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class ValidationError(AudexError):
|
|
121
|
+
"""Exception raised for validation errors."""
|
|
122
|
+
|
|
123
|
+
__slots__ = ("message", "reason")
|
|
124
|
+
|
|
125
|
+
default_message = "Validation failed"
|
|
126
|
+
code: t.ClassVar[int] = 0x12
|
|
127
|
+
|
|
128
|
+
def __init__(self, message: str | None = None, *, reason: str) -> None:
|
|
129
|
+
"""Initialize the exception.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
reason: Description of what failed validation.
|
|
133
|
+
message: Custom error message. If None, uses formatted default_message.
|
|
134
|
+
"""
|
|
135
|
+
self.reason = reason
|
|
136
|
+
full_message = message or f"{self.default_message}: {reason}"
|
|
137
|
+
super().__init__(full_message)
|
|
138
|
+
|
|
139
|
+
@classmethod
|
|
140
|
+
def from_pydantic_validation_err(cls, err: pyd.ValidationError) -> t.Self:
|
|
141
|
+
"""Create ValidationError from a Pydantic ValidationError."""
|
|
142
|
+
reason = "; ".join(f"{e['loc']}: {e['msg']}" for e in err.errors())
|
|
143
|
+
return cls(reason=reason)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class NoActiveSessionError(AudexError):
|
|
147
|
+
"""Exception raised when there is no active session."""
|
|
148
|
+
|
|
149
|
+
default_message = "No active session found. Please re-login to continue."
|
|
150
|
+
code: t.ClassVar[int] = 0x20
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class PermissionDeniedError(AudexError):
|
|
154
|
+
"""Exception raised for permission denied errors."""
|
|
155
|
+
|
|
156
|
+
default_message = "Permission denied. You do not have access to this resource."
|
|
157
|
+
code: t.ClassVar[int] = 0x21
|