|
| 1 | +"""HTTP server for intent recognition/handling.""" |
| 2 | + |
| 3 | +import io |
| 4 | +import logging |
| 5 | +import wave |
| 6 | +from pathlib import Path |
| 7 | +from typing import Any, Dict, Optional |
| 8 | + |
| 9 | +from flask import Response, request |
| 10 | + |
| 11 | +from wyoming.asr import Transcript |
| 12 | +from wyoming.client import AsyncClient |
| 13 | +from wyoming.error import Error |
| 14 | +from wyoming.intent import Intent, NotRecognized |
| 15 | +from wyoming.handle import Handled, NotHandled |
| 16 | + |
| 17 | +from .shared import get_app, get_argument_parser |
| 18 | + |
| 19 | +_DIR = Path(__file__).parent |
| 20 | +CONF_PATH = _DIR / "conf" / "intent.yaml" |
| 21 | + |
| 22 | + |
| 23 | +def main(): |
| 24 | + parser = get_argument_parser() |
| 25 | + parser.add_argument("--language", help="Language for text") |
| 26 | + args = parser.parse_args() |
| 27 | + logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO) |
| 28 | + |
| 29 | + app = get_app("intent", CONF_PATH, args) |
| 30 | + |
| 31 | + @app.route("/api/recognize-intent", methods=["POST", "GET"]) |
| 32 | + async def api_stt() -> Response: |
| 33 | + uri = request.args.get("uri", args.uri) |
| 34 | + if not uri: |
| 35 | + raise ValueError("URI is required") |
| 36 | + |
| 37 | + if request.method == "POST": |
| 38 | + text = request.data.decode() |
| 39 | + else: |
| 40 | + text = request.args.get("text", "") |
| 41 | + |
| 42 | + if not text: |
| 43 | + raise ValueError("Text is required") |
| 44 | + |
| 45 | + language = request.args.get("language", args.language) |
| 46 | + |
| 47 | + async with AsyncClient.from_uri(uri) as client: |
| 48 | + await client.write_event(Transcript(text=text, language=language).event()) |
| 49 | + |
| 50 | + while True: |
| 51 | + event = await client.read_event() |
| 52 | + if event is None: |
| 53 | + raise RuntimeError("Client disconnected") |
| 54 | + |
| 55 | + success = False |
| 56 | + type_name = "unknown" |
| 57 | + result: Dict[str, Any] = {} |
| 58 | + |
| 59 | + if Intent.is_type(event.type): |
| 60 | + success = True |
| 61 | + type_name = "intent" |
| 62 | + intent = Intent.from_event(event) |
| 63 | + result = intent.to_dict() |
| 64 | + elif Handled.is_type(event.type): |
| 65 | + success = True |
| 66 | + type_name = "handled" |
| 67 | + handled = Handled.from_event(event) |
| 68 | + result = handled.to_dict() |
| 69 | + elif NotRecognized.is_type(event.type): |
| 70 | + success = False |
| 71 | + type_name = "not-recognized" |
| 72 | + not_recognized = NotRecognized.from_event(event) |
| 73 | + result = not_recognized.to_dict() |
| 74 | + elif NotHandled.is_type(event.type): |
| 75 | + success = False |
| 76 | + type_name = "not-handled" |
| 77 | + not_handled = NotHandled.from_event(event) |
| 78 | + result = not_handled.to_dict() |
| 79 | + elif Error.is_type(event.type): |
| 80 | + error = Error.from_event(event) |
| 81 | + raise RuntimeError( |
| 82 | + f"Unexpected error from client: code={error.code}, text={error.text}" |
| 83 | + ) |
| 84 | + |
| 85 | + return {"success": success, "type": type_name, "result": result} |
| 86 | + |
| 87 | + app.run(args.host, args.port) |
| 88 | + |
| 89 | + |
| 90 | +if __name__ == "__main__": |
| 91 | + main() |
0 commit comments