Update project and configurations
This commit is contained in:
1
intelligent_cabin/app/__init__.py
Normal file
1
intelligent_cabin/app/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Application package for the intelligent cabin agent service."""
|
||||
BIN
intelligent_cabin/app/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/__pycache__/main.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/__pycache__/main.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/__pycache__/main.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/__pycache__/main.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/__pycache__/main.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/__pycache__/main.cpython-313.pyc
Normal file
Binary file not shown.
1
intelligent_cabin/app/core/__init__.py
Normal file
1
intelligent_cabin/app/core/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Core configuration package."""
|
||||
BIN
intelligent_cabin/app/core/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/bootstrap.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/bootstrap.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/bootstrap.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/bootstrap.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/bootstrap.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/bootstrap.cpython-313.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/config.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/config.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/config.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/core/__pycache__/config.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/core/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
323
intelligent_cabin/app/core/bootstrap.py
Normal file
323
intelligent_cabin/app/core/bootstrap.py
Normal file
@@ -0,0 +1,323 @@
|
||||
from app.core.config import settings
|
||||
from app.plugins.base import PluginRegistry
|
||||
from app.plugins.mock import MockPluginExecutor
|
||||
from app.services.agent_service import AgentService
|
||||
from app.services.classifier import (
|
||||
BertIntentClassifier,
|
||||
IntentClassifier,
|
||||
JointBertIntentClassifier,
|
||||
MockIntentClassifier,
|
||||
RemoteIntentClassifier,
|
||||
)
|
||||
from app.services.config_loader import ConfigLoader
|
||||
from app.services.intent_registry import IntentRegistry
|
||||
from app.services.joint_nlu import JointBertNLU
|
||||
from app.services.knowledge_llm import DashScopeKnowledgeLLM
|
||||
from app.services.knowledge_store import KnowledgeStore
|
||||
from app.services.multi_intent_detector import (
|
||||
BertMultiIntentDetector,
|
||||
JointBertMultiIntentDetector,
|
||||
MultiIntentDetector,
|
||||
)
|
||||
from app.services.planner import (
|
||||
CompositeWorkflowPlanner,
|
||||
DashScopeWorkflowPlanner,
|
||||
HeuristicWorkflowPlanner,
|
||||
TemplateWorkflowPlanner,
|
||||
WorkflowPlanner,
|
||||
)
|
||||
from app.services.response_policy import ResponsePolicy
|
||||
from app.services.rewrite_engine import ContextRewriteEngine
|
||||
from app.services.router import (
|
||||
HeuristicSlotExtractor,
|
||||
JointBertSlotExtractor,
|
||||
IntentRouter,
|
||||
Router,
|
||||
build_matcher_pipeline,
|
||||
)
|
||||
from app.services.session_store import InMemorySessionStore, RedisSessionStore, SessionStore
|
||||
from app.services.social import DashScopeSocialResponder, SocialResponder, SocialRouter
|
||||
|
||||
|
||||
def build_session_store(session_backend: str | None = None) -> SessionStore:
|
||||
backend = session_backend or settings.session_backend
|
||||
if backend == "memory":
|
||||
return InMemorySessionStore()
|
||||
if backend == "redis":
|
||||
return RedisSessionStore(
|
||||
redis_url=settings.redis_url,
|
||||
key_prefix=settings.redis_key_prefix,
|
||||
ttl_seconds=settings.session_ttl_seconds,
|
||||
)
|
||||
raise ValueError(f"Unsupported session backend: {backend}")
|
||||
|
||||
|
||||
def build_router(
|
||||
intent_registry: IntentRegistry,
|
||||
matcher_pipeline: str | None = None,
|
||||
classifier_backend: str | None = None,
|
||||
classifier: IntentClassifier | None = None,
|
||||
joint_nlu: JointBertNLU | None = None,
|
||||
) -> Router:
|
||||
active_pipeline = matcher_pipeline or settings.matcher_pipeline
|
||||
matcher_stages = [stage.strip() for stage in active_pipeline.split(",") if stage.strip()]
|
||||
if not matcher_stages:
|
||||
matcher_stages = ["classifier"]
|
||||
if matcher_stages != ["classifier"]:
|
||||
raise ValueError("Only classifier matcher pipeline is supported in bert-first mode")
|
||||
if settings.slot_extractor_backend not in {"heuristic", "joint_bert"}:
|
||||
raise ValueError(f"Unsupported slot extractor backend: {settings.slot_extractor_backend}")
|
||||
classifier = classifier or build_classifier(
|
||||
matcher_pipeline=active_pipeline,
|
||||
classifier_backend=classifier_backend,
|
||||
joint_nlu=joint_nlu,
|
||||
)
|
||||
if settings.slot_extractor_backend == "heuristic":
|
||||
slot_extractor = HeuristicSlotExtractor()
|
||||
else:
|
||||
if joint_nlu is None:
|
||||
raise ValueError("slot_extractor_backend=joint_bert requires a Joint NLU runtime")
|
||||
slot_extractor = JointBertSlotExtractor(joint_nlu)
|
||||
return IntentRouter(
|
||||
matcher=build_matcher_pipeline(
|
||||
intent_registry,
|
||||
matcher_stages,
|
||||
classifier=classifier,
|
||||
route_to_cloud_threshold=settings.local_route_to_cloud_threshold,
|
||||
clarify_margin_threshold=settings.local_clarify_margin_threshold,
|
||||
classifier_execute_score_threshold=settings.local_classifier_execute_score_threshold,
|
||||
classifier_execute_margin_threshold=settings.local_classifier_execute_margin_threshold,
|
||||
),
|
||||
slot_extractor=slot_extractor,
|
||||
)
|
||||
|
||||
|
||||
def build_classifier(
|
||||
matcher_pipeline: str | None = None,
|
||||
classifier_backend: str | None = None,
|
||||
joint_nlu: JointBertNLU | None = None,
|
||||
) -> IntentClassifier | None:
|
||||
active_pipeline = matcher_pipeline or settings.matcher_pipeline
|
||||
active_backend = classifier_backend or settings.classifier_backend
|
||||
if "classifier" not in active_pipeline:
|
||||
return None
|
||||
fallback = MockIntentClassifier(
|
||||
threshold=settings.classifier_threshold,
|
||||
top_k=settings.classifier_top_k,
|
||||
)
|
||||
if active_backend == "mock":
|
||||
return fallback
|
||||
if active_backend == "bert":
|
||||
classifier = BertIntentClassifier(
|
||||
model_path=settings.classifier_model_path,
|
||||
threshold=settings.classifier_bert_threshold,
|
||||
label_map_path=settings.classifier_label_map_path or None,
|
||||
fallback=fallback,
|
||||
top_k=settings.classifier_top_k,
|
||||
)
|
||||
if settings.classifier_warmup_enabled:
|
||||
classifier.warmup(settings.classifier_warmup_text)
|
||||
return classifier
|
||||
if active_backend == "joint_bert":
|
||||
runtime = joint_nlu or build_joint_nlu()
|
||||
classifier = JointBertIntentClassifier(
|
||||
nlu=runtime,
|
||||
threshold=settings.joint_nlu_intent_threshold if settings.joint_nlu_intent_threshold > 0 else 0.0,
|
||||
top_k=settings.joint_nlu_top_k,
|
||||
)
|
||||
if settings.classifier_warmup_enabled:
|
||||
classifier.warmup(settings.classifier_warmup_text)
|
||||
return classifier
|
||||
if active_backend == "remote":
|
||||
return RemoteIntentClassifier(
|
||||
endpoint=settings.classifier_remote_url,
|
||||
timeout_seconds=settings.classifier_remote_timeout_seconds,
|
||||
threshold=settings.classifier_threshold,
|
||||
fallback=fallback,
|
||||
label_map_path=settings.classifier_label_map_path or None,
|
||||
top_k=settings.classifier_top_k,
|
||||
)
|
||||
raise ValueError(f"Unsupported classifier backend: {active_backend}")
|
||||
|
||||
|
||||
def build_agent_service() -> AgentService:
|
||||
return build_agent_service_with_runtime()
|
||||
|
||||
|
||||
def build_agent_service_with_runtime(
|
||||
matcher_pipeline: str | None = None,
|
||||
classifier_backend: str | None = None,
|
||||
session_backend: str | None = None,
|
||||
) -> AgentService:
|
||||
runtime_bundle = load_runtime_bundle()
|
||||
intent_registry = runtime_bundle.intent_registry
|
||||
active_classifier_backend = classifier_backend or settings.classifier_backend
|
||||
needs_joint_nlu = active_classifier_backend == "joint_bert" or settings.slot_extractor_backend == "joint_bert"
|
||||
joint_nlu = build_joint_nlu() if needs_joint_nlu else None
|
||||
classifier = build_classifier(
|
||||
matcher_pipeline=matcher_pipeline or settings.matcher_pipeline,
|
||||
classifier_backend=active_classifier_backend,
|
||||
joint_nlu=joint_nlu,
|
||||
)
|
||||
planner_clause_classifier = (
|
||||
classifier
|
||||
if settings.planner_clause_classifier_enabled and active_classifier_backend in {"bert", "remote", "joint_bert"}
|
||||
else None
|
||||
)
|
||||
multi_intent_detector = build_multi_intent_detector(
|
||||
classifier_backend=classifier_backend,
|
||||
joint_nlu=joint_nlu,
|
||||
)
|
||||
plugin_registry = PluginRegistry()
|
||||
MockPluginExecutor().register(plugin_registry)
|
||||
return AgentService(
|
||||
intent_registry=intent_registry,
|
||||
router=build_router(
|
||||
intent_registry,
|
||||
matcher_pipeline=matcher_pipeline,
|
||||
classifier_backend=active_classifier_backend,
|
||||
classifier=classifier,
|
||||
joint_nlu=joint_nlu,
|
||||
),
|
||||
plugins=plugin_registry,
|
||||
session_store=build_session_store(session_backend=session_backend),
|
||||
rewrite_engine=runtime_bundle.rewrite_engine,
|
||||
response_policy=ResponsePolicy(
|
||||
templates=runtime_bundle.response_templates,
|
||||
intent_hints=runtime_bundle.intent_hints,
|
||||
),
|
||||
dialog_rules=runtime_bundle.dialog_rules,
|
||||
dialog_act_engine=runtime_bundle.dialog_act_engine,
|
||||
planner=build_planner(
|
||||
runtime_bundle.workflow_templates,
|
||||
clause_classifier=planner_clause_classifier,
|
||||
multi_intent_detector=multi_intent_detector,
|
||||
joint_nlu=joint_nlu,
|
||||
),
|
||||
social_router=SocialRouter(),
|
||||
social_responder=build_social_responder(),
|
||||
knowledge_llm=build_knowledge_llm(),
|
||||
)
|
||||
|
||||
|
||||
def build_intent_registry() -> IntentRegistry:
|
||||
return load_runtime_bundle().intent_registry
|
||||
|
||||
|
||||
def load_runtime_bundle():
|
||||
return ConfigLoader(
|
||||
domain_path=settings.domain_config_path,
|
||||
action_path=settings.action_config_path,
|
||||
response_path=settings.response_config_path,
|
||||
form_path=settings.form_config_path,
|
||||
rule_path=settings.rule_config_path,
|
||||
dialog_act_path=settings.dialog_act_config_path,
|
||||
workflow_path=settings.workflow_config_path,
|
||||
legacy_intent_path=settings.intent_config_path,
|
||||
context_rewrite_path=settings.context_rewrite_config_path,
|
||||
).load()
|
||||
|
||||
|
||||
def build_joint_nlu() -> JointBertNLU:
|
||||
runtime = JointBertNLU(
|
||||
model_path=settings.joint_nlu_model_path,
|
||||
intent_threshold=settings.joint_nlu_intent_threshold if settings.joint_nlu_intent_threshold > 0 else None,
|
||||
top_k=settings.joint_nlu_top_k,
|
||||
)
|
||||
if settings.classifier_warmup_enabled:
|
||||
runtime.warmup(settings.classifier_warmup_text)
|
||||
return runtime
|
||||
|
||||
|
||||
def build_multi_intent_detector(
|
||||
classifier_backend: str | None = None,
|
||||
joint_nlu: JointBertNLU | None = None,
|
||||
) -> MultiIntentDetector | None:
|
||||
active_backend = classifier_backend or settings.classifier_backend
|
||||
if not settings.planner_multi_intent_detector_enabled:
|
||||
return None
|
||||
if active_backend not in {"bert", "joint_bert"}:
|
||||
return None
|
||||
if active_backend == "joint_bert":
|
||||
runtime = joint_nlu or build_joint_nlu()
|
||||
detector = JointBertMultiIntentDetector(
|
||||
nlu=runtime,
|
||||
threshold=settings.planner_multi_intent_detector_threshold if settings.planner_multi_intent_detector_threshold > 0 else None,
|
||||
top_k=settings.planner_multi_intent_detector_top_k,
|
||||
max_labels=settings.planner_multi_intent_detector_max_labels,
|
||||
)
|
||||
if settings.classifier_warmup_enabled:
|
||||
detector.warmup(settings.classifier_warmup_text)
|
||||
return detector
|
||||
detector_model_path = settings.planner_multi_intent_detector_model_path or settings.classifier_model_path
|
||||
detector = BertMultiIntentDetector(
|
||||
model_path=detector_model_path,
|
||||
threshold=settings.planner_multi_intent_detector_threshold,
|
||||
top_k=settings.planner_multi_intent_detector_top_k,
|
||||
max_labels=settings.planner_multi_intent_detector_max_labels,
|
||||
)
|
||||
if settings.classifier_warmup_enabled:
|
||||
detector.warmup(settings.classifier_warmup_text)
|
||||
return detector
|
||||
|
||||
|
||||
def build_planner(
|
||||
workflow_templates=None,
|
||||
clause_classifier: IntentClassifier | None = None,
|
||||
multi_intent_detector: MultiIntentDetector | None = None,
|
||||
joint_nlu: JointBertNLU | None = None,
|
||||
) -> WorkflowPlanner:
|
||||
template_planner = TemplateWorkflowPlanner(
|
||||
workflow_templates,
|
||||
clause_classifier=clause_classifier,
|
||||
multi_intent_detector=multi_intent_detector,
|
||||
joint_nlu=joint_nlu,
|
||||
classifier_weight=settings.planner_clause_classifier_weight,
|
||||
model_only_threshold=settings.planner_clause_model_only_threshold,
|
||||
)
|
||||
local_first = CompositeWorkflowPlanner(
|
||||
[
|
||||
template_planner,
|
||||
HeuristicWorkflowPlanner(
|
||||
clause_classifier=clause_classifier,
|
||||
multi_intent_detector=multi_intent_detector,
|
||||
joint_nlu=joint_nlu,
|
||||
classifier_weight=settings.planner_clause_classifier_weight,
|
||||
model_only_threshold=settings.planner_clause_model_only_threshold,
|
||||
),
|
||||
]
|
||||
)
|
||||
if settings.planner_backend == "heuristic":
|
||||
return local_first
|
||||
if settings.planner_backend == "dashscope":
|
||||
cloud_planner = DashScopeWorkflowPlanner(
|
||||
base_url=settings.planner_base_url,
|
||||
api_key=settings.planner_api_key,
|
||||
model_name=settings.planner_model_name,
|
||||
timeout_seconds=settings.planner_timeout_seconds,
|
||||
fallback=local_first,
|
||||
joint_nlu=joint_nlu,
|
||||
)
|
||||
return CompositeWorkflowPlanner([local_first, cloud_planner])
|
||||
raise ValueError(f"Unsupported planner backend: {settings.planner_backend}")
|
||||
|
||||
|
||||
def build_social_responder() -> SocialResponder:
|
||||
return DashScopeSocialResponder(
|
||||
base_url=settings.planner_base_url,
|
||||
api_key=settings.planner_api_key,
|
||||
model_name=settings.planner_model_name,
|
||||
timeout_seconds=settings.planner_timeout_seconds,
|
||||
)
|
||||
|
||||
|
||||
def build_knowledge_llm() -> DashScopeKnowledgeLLM:
|
||||
"""构建知识库 LLM 问答器(与 planner 共用 DashScope 配置)。"""
|
||||
store = KnowledgeStore(settings.knowledge_dir)
|
||||
return DashScopeKnowledgeLLM(
|
||||
base_url=settings.planner_base_url,
|
||||
api_key=settings.planner_api_key,
|
||||
model_name=settings.planner_model_name,
|
||||
knowledge_store=store,
|
||||
timeout_seconds=12.0,
|
||||
)
|
||||
61
intelligent_cabin/app/core/config.py
Normal file
61
intelligent_cabin/app/core/config.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
app_name: str = "Intelligent Cabin Agent"
|
||||
app_env: str = "dev"
|
||||
app_host: str = "0.0.0.0"
|
||||
app_port: int = 8000
|
||||
intent_config_path: str = "app/data/intents.json"
|
||||
domain_config_path: str = "config/domain.yml"
|
||||
action_config_path: str = "config/actions.yml"
|
||||
response_config_path: str = "config/responses.yml"
|
||||
form_config_path: str = "config/forms.yml"
|
||||
rule_config_path: str = "config/rules.yml"
|
||||
dialog_act_config_path: str = "config/dialog_acts.yml"
|
||||
workflow_config_path: str = "config/workflows.yml"
|
||||
# 本地上下文改写引擎配置(不同设备可切换不同 yml 文件)
|
||||
context_rewrite_config_path: str = "config/context_rewrite.yml"
|
||||
session_backend: str = "memory"
|
||||
redis_url: str = "redis://127.0.0.1:6379/0"
|
||||
redis_key_prefix: str = "agent:session"
|
||||
session_ttl_seconds: int = 86400
|
||||
matcher_pipeline: str = "classifier"
|
||||
slot_extractor_backend: str = "joint_bert"
|
||||
classifier_backend: str = "joint_bert"
|
||||
classifier_threshold: float = 1.2
|
||||
classifier_bert_threshold: float = 0.0
|
||||
classifier_top_k: int = 3
|
||||
classifier_model_path: str = ""
|
||||
classifier_label_map_path: str = ""
|
||||
classifier_warmup_enabled: bool = True
|
||||
classifier_warmup_text: str = "打开车窗"
|
||||
classifier_remote_url: str = ""
|
||||
classifier_remote_timeout_seconds: float = 3.0
|
||||
joint_nlu_model_path: str = "models/local_joint_bert_nlu"
|
||||
joint_nlu_intent_threshold: float = 0.0
|
||||
joint_nlu_top_k: int = 3
|
||||
local_route_to_cloud_threshold: float = 0.75
|
||||
local_clarify_margin_threshold: float = 0.12
|
||||
local_classifier_execute_score_threshold: float = 0.55
|
||||
local_classifier_execute_margin_threshold: float = 0.18
|
||||
planner_backend: str = "heuristic"
|
||||
planner_base_url: str = ""
|
||||
planner_api_key: str = ""
|
||||
planner_model_name: str = ""
|
||||
planner_timeout_seconds: float = 6.0
|
||||
planner_clause_classifier_enabled: bool = True
|
||||
planner_clause_classifier_weight: float = 1.6
|
||||
planner_clause_model_only_threshold: float = 0.62
|
||||
planner_multi_intent_detector_enabled: bool = True
|
||||
planner_multi_intent_detector_model_path: str = ""
|
||||
planner_multi_intent_detector_threshold: float = 0.0
|
||||
planner_multi_intent_detector_top_k: int = 8
|
||||
planner_multi_intent_detector_max_labels: int = 4
|
||||
# 本地知识库目录(存放 .md 格式知识文档)
|
||||
knowledge_dir: str = "config/knowledge"
|
||||
|
||||
model_config = SettingsConfigDict(env_file=".env", env_prefix="AGENT_")
|
||||
|
||||
|
||||
settings = Settings()
|
||||
@@ -0,0 +1,42 @@
|
||||
{"text":"空调先别吹了,关掉吧","expected_label":"cabin_ac_off","category":"business"}
|
||||
{"text":"车里有点闷,把冷气开起来","expected_label":"cabin_ac_on","category":"business"}
|
||||
{"text":"前挡有雾,赶紧除一下","expected_label":"cabin_defog_front_on","category":"business"}
|
||||
{"text":"后玻璃起雾了,开后挡除雾","expected_label":"cabin_defog_rear_on","category":"business"}
|
||||
{"text":"风太猛了,给我调小一档","expected_label":"cabin_fan_down","category":"business"}
|
||||
{"text":"出风再大一点","expected_label":"cabin_fan_up","category":"business"}
|
||||
{"text":"把灯熄了吧","expected_label":"cabin_lights_off","category":"business"}
|
||||
{"text":"天快黑了,把大灯打开","expected_label":"cabin_lights_on","category":"business"}
|
||||
{"text":"锁上所有车门","expected_label":"cabin_lock_doors","category":"business"}
|
||||
{"text":"两边后视镜收起来","expected_label":"cabin_mirror_fold","category":"business"}
|
||||
{"text":"把后视镜展开准备出发","expected_label":"cabin_mirror_unfold","category":"business"}
|
||||
{"text":"路线不用导了,结束导航","expected_label":"cabin_nav_cancel","category":"business"}
|
||||
{"text":"直接带我去龙阳路地铁站","expected_label":"cabin_nav_to","category":"business"}
|
||||
{"text":"这首不想听了,切到下一首","expected_label":"cabin_next_track","category":"business"}
|
||||
{"text":"音乐先停一下","expected_label":"cabin_pause_music","category":"business"}
|
||||
{"text":"放点适合夜里开车听的歌","expected_label":"cabin_play_music","category":"business"}
|
||||
{"text":"切回上一首","expected_label":"cabin_previous_track","category":"business"}
|
||||
{"text":"座椅加热可以关了","expected_label":"cabin_seat_heat_off","category":"business"}
|
||||
{"text":"主驾座椅加热打开","expected_label":"cabin_seat_heat_on","category":"business"}
|
||||
{"text":"把车内温度定在二十二度","expected_label":"cabin_set_ac","category":"business"}
|
||||
{"text":"天窗给我合上","expected_label":"cabin_sunroof_close","category":"business"}
|
||||
{"text":"把天窗翘起来透透气","expected_label":"cabin_sunroof_open","category":"business"}
|
||||
{"text":"车门解锁一下","expected_label":"cabin_unlock_doors","category":"business"}
|
||||
{"text":"声音太响了,压低点","expected_label":"cabin_volume_down","category":"business"}
|
||||
{"text":"音响直接静音","expected_label":"cabin_volume_mute","category":"business"}
|
||||
{"text":"把媒体音量往上加","expected_label":"cabin_volume_up","category":"business"}
|
||||
{"text":"把四个窗都关严","expected_label":"cabin_window_close","category":"business"}
|
||||
{"text":"左前窗打开一点","expected_label":"cabin_window_open","category":"business"}
|
||||
{"text":"雨停了,把雨刮停掉","expected_label":"cabin_wiper_off","category":"business"}
|
||||
{"text":"开始刮雨刷","expected_label":"cabin_wiper_on","category":"business"}
|
||||
{"text":"订单A551201别发了,撤单","expected_label":"cs_cancel_order","category":"business"}
|
||||
{"text":"A661202这个包裹送到哪了","expected_label":"cs_query_logistics","category":"business"}
|
||||
{"text":"帮我看看A771203这单处理进度","expected_label":"cs_query_order","category":"business"}
|
||||
{"text":"这个事情我要真人来跟进","expected_label":"cs_transfer_human","category":"business"}
|
||||
{"text":"你好呀","expected_label":"__social__","category":"social"}
|
||||
{"text":"早上好,今天心情不错","expected_label":"__social__","category":"social"}
|
||||
{"text":"你叫什么名字来着","expected_label":"__social__","category":"social"}
|
||||
{"text":"今天天气挺舒服的","expected_label":"__social__","category":"social"}
|
||||
{"text":"帮我点份炸鸡外卖","expected_label":"__out_of_scope__","category":"out_of_scope"}
|
||||
{"text":"给我订明晚的酒店","expected_label":"__out_of_scope__","category":"out_of_scope"}
|
||||
{"text":"人活着的意义是什么","expected_label":"__out_of_scope__","category":"out_of_scope"}
|
||||
{"text":"推荐一部悬疑电影","expected_label":"__out_of_scope__","category":"out_of_scope"}
|
||||
@@ -0,0 +1,37 @@
|
||||
{"text":"车里闷,给我透个气,再放点轻松的歌","expected_intent_ids":["cabin_window_open","cabin_play_music"],"category":"cabin_parallel"}
|
||||
{"text":"先把空调开起来,顺手把窗户关好","expected_intent_ids":["cabin_ac_on","cabin_window_close"],"category":"cabin_parallel"}
|
||||
{"text":"带我去公司,路上播点民谣","expected_intent_ids":["cabin_nav_to","cabin_play_music"],"category":"cabin_parallel"}
|
||||
{"text":"有点热,把温度打到二十一度,再来点音乐","expected_intent_ids":["cabin_set_ac","cabin_play_music"],"category":"cabin_parallel"}
|
||||
{"text":"导航去虹桥站,然后把空调打开","expected_intent_ids":["cabin_nav_to","cabin_ac_on"],"category":"cabin_sequence"}
|
||||
{"text":"前挡看不清了,开除雾,风也加大一点","expected_intent_ids":["cabin_defog_front_on","cabin_fan_up"],"category":"cabin_parallel"}
|
||||
{"text":"后面玻璃有雾,先除雾,再把窗关上","expected_intent_ids":["cabin_defog_rear_on","cabin_window_close"],"category":"cabin_sequence"}
|
||||
{"text":"把空调开了,风别太小,再来首歌","expected_intent_ids":["cabin_ac_on","cabin_fan_up","cabin_play_music"],"category":"cabin_parallel"}
|
||||
{"text":"去浦东机场,车里凉一点,顺便放点歌","expected_intent_ids":["cabin_nav_to","cabin_set_ac","cabin_play_music"],"category":"cabin_parallel"}
|
||||
{"text":"先开一点窗,别那么闷,再把温度调低","expected_intent_ids":["cabin_window_open","cabin_set_ac"],"category":"cabin_parallel"}
|
||||
{"text":"把四个窗都关了,然后播点轻音乐","expected_intent_ids":["cabin_window_close","cabin_play_music"],"category":"cabin_sequence"}
|
||||
{"text":"把天窗打开透口气,再开空调","expected_intent_ids":["cabin_sunroof_open","cabin_ac_on"],"category":"cabin_parallel"}
|
||||
{"text":"开导航去徐家汇,顺便把风量调大","expected_intent_ids":["cabin_nav_to","cabin_fan_up"],"category":"cabin_parallel"}
|
||||
{"text":"音乐停一下,然后导航到公司","expected_intent_ids":["cabin_pause_music","cabin_nav_to"],"category":"cabin_sequence"}
|
||||
{"text":"锁车门,再把后视镜收起来","expected_intent_ids":["cabin_lock_doors","cabin_mirror_fold"],"category":"cabin_sequence"}
|
||||
{"text":"把车门解锁,再把镜子展开","expected_intent_ids":["cabin_unlock_doors","cabin_mirror_unfold"],"category":"cabin_sequence"}
|
||||
{"text":"路线别导了,音乐也停一下","expected_intent_ids":["cabin_nav_cancel","cabin_pause_music"],"category":"cabin_parallel"}
|
||||
{"text":"温度调到二十三度,风稍微小一点","expected_intent_ids":["cabin_set_ac","cabin_fan_down"],"category":"cabin_parallel"}
|
||||
{"text":"查下订单A812301,如果还没发货就取消掉","expected_intent_ids":["cs_query_order","cs_cancel_order"],"category":"cs_conditional"}
|
||||
{"text":"帮我看A812302物流,要是太慢就转人工","expected_intent_ids":["cs_query_logistics","cs_transfer_human"],"category":"cs_conditional"}
|
||||
{"text":"先查一下A812303这单进度,再帮我转人工客服","expected_intent_ids":["cs_query_order","cs_transfer_human"],"category":"cs_sequence"}
|
||||
{"text":"订单A812304先查下状态,再看看物流到了哪","expected_intent_ids":["cs_query_order","cs_query_logistics"],"category":"cs_sequence"}
|
||||
{"text":"我想先看看A812305有没有发货,没发的话直接撤单","expected_intent_ids":["cs_query_order","cs_cancel_order"],"category":"cs_conditional"}
|
||||
{"text":"把空调关掉","expected_intent_ids":["cabin_ac_off"],"category":"single_guard"}
|
||||
{"text":"帮我开一下前挡除雾","expected_intent_ids":["cabin_defog_front_on"],"category":"single_guard"}
|
||||
{"text":"风太大了,往小调一点","expected_intent_ids":["cabin_fan_down"],"category":"single_guard"}
|
||||
{"text":"给我导航到龙阳路","expected_intent_ids":["cabin_nav_to"],"category":"single_guard"}
|
||||
{"text":"来点轻音乐","expected_intent_ids":["cabin_play_music"],"category":"single_guard"}
|
||||
{"text":"把左前窗降一点","expected_intent_ids":["cabin_window_open"],"category":"single_guard"}
|
||||
{"text":"订单A812306不要了,直接取消","expected_intent_ids":["cs_cancel_order"],"category":"single_guard"}
|
||||
{"text":"A812307这个快递到哪了","expected_intent_ids":["cs_query_logistics"],"category":"single_guard"}
|
||||
{"text":"导航去公司,再把空调开开,歌也放起来","expected_intent_ids":["cabin_nav_to","cabin_ac_on","cabin_play_music"],"category":"cabin_parallel"}
|
||||
{"text":"把雨刮打开,顺便关下车窗","expected_intent_ids":["cabin_wiper_on","cabin_window_close"],"category":"cabin_parallel"}
|
||||
{"text":"雨停了,雨刮关掉,再把窗开一点","expected_intent_ids":["cabin_wiper_off","cabin_window_open"],"category":"cabin_sequence"}
|
||||
{"text":"把天窗合上,然后把音乐暂停","expected_intent_ids":["cabin_sunroof_close","cabin_pause_music"],"category":"cabin_sequence"}
|
||||
{"text":"先把音量调大,再切下一首","expected_intent_ids":["cabin_volume_up","cabin_next_track"],"category":"cabin_parallel"}
|
||||
{"text":"静音之后切回上一首","expected_intent_ids":["cabin_volume_mute","cabin_previous_track"],"category":"cabin_sequence"}
|
||||
@@ -0,0 +1,72 @@
|
||||
{"text": "打开车窗并播放音乐", "intent_ids": ["cabin_window_open", "cabin_play_music"]}
|
||||
{"text": "把空调打开然后开下车窗", "intent_ids": ["cabin_ac_on", "cabin_window_open"]}
|
||||
{"text": "导航去公司再来点轻音乐", "intent_ids": ["cabin_nav_to", "cabin_play_music"]}
|
||||
{"text": "把空调调到22度并播放周杰伦", "intent_ids": ["cabin_set_ac", "cabin_play_music"]}
|
||||
{"text": "打开空调顺便把车窗关上", "intent_ids": ["cabin_ac_on", "cabin_window_close"]}
|
||||
{"text": "导航去虹桥机场然后把空调调到21度", "intent_ids": ["cabin_nav_to", "cabin_set_ac"]}
|
||||
{"text": "开下窗,再来首歌", "intent_ids": ["cabin_window_open", "cabin_play_music"]}
|
||||
{"text": "空调开起来,风再大一点", "intent_ids": ["cabin_ac_on", "cabin_fan_up"]}
|
||||
{"text": "把空调调低一点,再把风量开大", "intent_ids": ["cabin_set_ac", "cabin_fan_up"]}
|
||||
{"text": "外面太吵了,关窗,然后放点轻音乐", "intent_ids": ["cabin_window_close", "cabin_play_music"]}
|
||||
{"text": "前挡起雾了,开除雾,再把风量调大", "intent_ids": ["cabin_defog_front_on", "cabin_fan_up"]}
|
||||
{"text": "后挡有雾,除一下,再把窗户关好", "intent_ids": ["cabin_defog_rear_on", "cabin_window_close"]}
|
||||
{"text": "把空调设到24度,顺便透透气", "intent_ids": ["cabin_set_ac", "cabin_window_open"]}
|
||||
{"text": "导航到公司并打开空调", "intent_ids": ["cabin_nav_to", "cabin_ac_on"]}
|
||||
{"text": "去徐家汇,车里太热了顺便降温", "intent_ids": ["cabin_nav_to", "cabin_set_ac"]}
|
||||
{"text": "来点歌,再把车窗打开一点", "intent_ids": ["cabin_play_music", "cabin_window_open"]}
|
||||
{"text": "把风量调小一点,然后放点音乐", "intent_ids": ["cabin_fan_down", "cabin_play_music"]}
|
||||
{"text": "开空调,关窗,播放轻音乐", "intent_ids": ["cabin_ac_on", "cabin_window_close", "cabin_play_music"]}
|
||||
{"text": "导航去最近的充电站,再开一点窗透气", "intent_ids": ["cabin_nav_to", "cabin_window_open"]}
|
||||
{"text": "把温度调到20度,关上车窗,再来一首夜曲", "intent_ids": ["cabin_set_ac", "cabin_window_close", "cabin_play_music"]}
|
||||
{"text": "查一下订单A700001,如果还没发货就取消", "intent_ids": ["cs_query_order", "cs_cancel_order"]}
|
||||
{"text": "帮我看下A700002这单物流,没到的话转人工", "intent_ids": ["cs_query_logistics", "cs_transfer_human"]}
|
||||
{"text": "查下订单A700003现在啥情况,然后帮我转人工", "intent_ids": ["cs_query_order", "cs_transfer_human"]}
|
||||
{"text": "先查订单A700004,再查物流进度", "intent_ids": ["cs_query_order", "cs_query_logistics"]}
|
||||
{"text": "打开空调并导航去公司再放点歌", "intent_ids": ["cabin_ac_on", "cabin_nav_to", "cabin_play_music"]}
|
||||
{"text": "帮我透透气,然后把温度调到21度", "intent_ids": ["cabin_window_open", "cabin_set_ac"]}
|
||||
{"text": "开前挡除雾,再把风开大一点", "intent_ids": ["cabin_defog_front_on", "cabin_fan_up"]}
|
||||
{"text": "后窗除雾后把车窗关上", "intent_ids": ["cabin_defog_rear_on", "cabin_window_close"]}
|
||||
{"text": "导航到浦东机场,空调开一下,来点民谣", "intent_ids": ["cabin_nav_to", "cabin_ac_on", "cabin_play_music"]}
|
||||
{"text": "把车里弄凉快点,顺便放点轻音乐", "intent_ids": ["cabin_set_ac", "cabin_play_music"]}
|
||||
{"text": "打开车窗和空调", "intent_ids": ["cabin_window_open", "cabin_ac_on"]}
|
||||
{"text": "开窗和开空调", "intent_ids": ["cabin_window_open", "cabin_ac_on"]}
|
||||
{"text": "把车窗打开,空调也打开", "intent_ids": ["cabin_window_open", "cabin_ac_on"]}
|
||||
{"text": "车里闷,给我透个气,再放点轻松的歌", "intent_ids": ["cabin_window_open", "cabin_play_music"]}
|
||||
{"text": "透透气,再来一首黄昏", "intent_ids": ["cabin_window_open", "cabin_play_music"]}
|
||||
{"text": "先把空调开起来,顺手把窗户关好", "intent_ids": ["cabin_ac_on", "cabin_window_close"]}
|
||||
{"text": "带我去公司,路上播点民谣", "intent_ids": ["cabin_nav_to", "cabin_play_music"]}
|
||||
{"text": "有点热,把温度打到二十一度,再来点音乐", "intent_ids": ["cabin_set_ac", "cabin_play_music"]}
|
||||
{"text": "导航去虹桥站,然后把空调打开", "intent_ids": ["cabin_nav_to", "cabin_ac_on"]}
|
||||
{"text": "前挡看不清了,开除雾,风也加大一点", "intent_ids": ["cabin_defog_front_on", "cabin_fan_up"]}
|
||||
{"text": "后面玻璃有雾,先除雾,再把窗关上", "intent_ids": ["cabin_defog_rear_on", "cabin_window_close"]}
|
||||
{"text": "把空调开了,风别太小,再来首歌", "intent_ids": ["cabin_ac_on", "cabin_fan_up", "cabin_play_music"]}
|
||||
{"text": "去浦东机场,车里凉一点,顺便放点歌", "intent_ids": ["cabin_nav_to", "cabin_set_ac", "cabin_play_music"]}
|
||||
{"text": "先开一点窗,别那么闷,再把温度调低", "intent_ids": ["cabin_window_open", "cabin_set_ac"]}
|
||||
{"text": "把四个窗都关了,然后播点轻音乐", "intent_ids": ["cabin_window_close", "cabin_play_music"]}
|
||||
{"text": "把天窗打开透口气,再开空调", "intent_ids": ["cabin_sunroof_open", "cabin_ac_on"]}
|
||||
{"text": "开导航去徐家汇,顺便把风量调大", "intent_ids": ["cabin_nav_to", "cabin_fan_up"]}
|
||||
{"text": "音乐停一下,然后导航到公司", "intent_ids": ["cabin_pause_music", "cabin_nav_to"]}
|
||||
{"text": "锁车门,再把后视镜收起来", "intent_ids": ["cabin_lock_doors", "cabin_mirror_fold"]}
|
||||
{"text": "把车门解锁,再把镜子展开", "intent_ids": ["cabin_unlock_doors", "cabin_mirror_unfold"]}
|
||||
{"text": "路线别导了,音乐也停一下", "intent_ids": ["cabin_nav_cancel", "cabin_pause_music"]}
|
||||
{"text": "温度调到二十三度,风稍微小一点", "intent_ids": ["cabin_set_ac", "cabin_fan_down"]}
|
||||
{"text": "查下订单A812301,如果还没发货就取消掉", "intent_ids": ["cs_query_order", "cs_cancel_order"]}
|
||||
{"text": "帮我看A812302物流,要是太慢就转人工", "intent_ids": ["cs_query_logistics", "cs_transfer_human"]}
|
||||
{"text": "先查一下A812303这单进度,再帮我转人工客服", "intent_ids": ["cs_query_order", "cs_transfer_human"]}
|
||||
{"text": "订单A812304先查下状态,再看看物流到了哪", "intent_ids": ["cs_query_order", "cs_query_logistics"]}
|
||||
{"text": "我想先看看A812305有没有发货,没发的话直接撤单", "intent_ids": ["cs_query_order", "cs_cancel_order"]}
|
||||
{"text": "导航去公司,再把空调开开,歌也放起来", "intent_ids": ["cabin_nav_to", "cabin_ac_on", "cabin_play_music"]}
|
||||
{"text": "把雨刮打开,顺便关下车窗", "intent_ids": ["cabin_wiper_on", "cabin_window_close"]}
|
||||
{"text": "雨停了,雨刮关掉,再把窗开一点", "intent_ids": ["cabin_wiper_off", "cabin_window_open"]}
|
||||
{"text": "把天窗合上,然后把音乐暂停", "intent_ids": ["cabin_sunroof_close", "cabin_pause_music"]}
|
||||
{"text": "先把音量调大,再切下一首", "intent_ids": ["cabin_volume_up", "cabin_next_track"]}
|
||||
{"text": "静音之后切回上一首", "intent_ids": ["cabin_volume_mute", "cabin_previous_track"]}
|
||||
{"text": "来点music", "intent_ids": ["cabin_play_music"]}
|
||||
{"text": "来点音乐,想听黄昏", "intent_ids": ["cabin_play_music"]}
|
||||
{"text": "放周杰伦的黄昏", "intent_ids": ["cabin_play_music"]}
|
||||
{"text": "来一首黄昏", "intent_ids": ["cabin_play_music"]}
|
||||
{"text": "给我放黄昏", "intent_ids": ["cabin_play_music"]}
|
||||
{"text": "开窗顺便放点歌", "intent_ids": ["cabin_window_open", "cabin_play_music"]}
|
||||
{"text": "导航到公司同时放点轻音乐", "intent_ids": ["cabin_nav_to", "cabin_play_music"]}
|
||||
{"text": "空调打开再把风量调大", "intent_ids": ["cabin_ac_on", "cabin_fan_up"]}
|
||||
{"text": "关窗再暂停音乐", "intent_ids": ["cabin_window_close", "cabin_pause_music"]}
|
||||
35
intelligent_cabin/app/data/bert_intent_test.jsonl
Normal file
35
intelligent_cabin/app/data/bert_intent_test.jsonl
Normal file
@@ -0,0 +1,35 @@
|
||||
{"text":"查一下订单A700001现在什么状态","intent_id":"cs_query_order"}
|
||||
{"text":"我的订单A700002到哪一步了","intent_id":"cs_query_order"}
|
||||
{"text":"帮我看看A700003这个订单","intent_id":"cs_query_order"}
|
||||
{"text":"订单A700004现在处理到哪里","intent_id":"cs_query_order"}
|
||||
{"text":"确认下A700005订单状态","intent_id":"cs_query_order"}
|
||||
{"text":"帮我查A800001物流进度","intent_id":"cs_query_logistics"}
|
||||
{"text":"快递A800002到哪儿了","intent_id":"cs_query_logistics"}
|
||||
{"text":"看看A800003配送状态","intent_id":"cs_query_logistics"}
|
||||
{"text":"订单A800004物流更新了吗","intent_id":"cs_query_logistics"}
|
||||
{"text":"查询A800005的快递信息","intent_id":"cs_query_logistics"}
|
||||
{"text":"帮我取消A900001这个订单","intent_id":"cs_cancel_order"}
|
||||
{"text":"A900002别要了给我撤销","intent_id":"cs_cancel_order"}
|
||||
{"text":"把订单A900003取消掉","intent_id":"cs_cancel_order"}
|
||||
{"text":"我不要A900004了","intent_id":"cs_cancel_order"}
|
||||
{"text":"撤销一下A900005订单","intent_id":"cs_cancel_order"}
|
||||
{"text":"我要找人工客服处理","intent_id":"cs_transfer_human"}
|
||||
{"text":"现在转人工","intent_id":"cs_transfer_human"}
|
||||
{"text":"麻烦给我接人工服务","intent_id":"cs_transfer_human"}
|
||||
{"text":"帮我呼叫真人客服","intent_id":"cs_transfer_human"}
|
||||
{"text":"别机器人了我要人工","intent_id":"cs_transfer_human"}
|
||||
{"text":"导航到公司停车场","intent_id":"cabin_nav_to"}
|
||||
{"text":"带我去浦东机场T2","intent_id":"cabin_nav_to"}
|
||||
{"text":"去最近的服务区","intent_id":"cabin_nav_to"}
|
||||
{"text":"我要去徐家汇","intent_id":"cabin_nav_to"}
|
||||
{"text":"开导航去虹桥机场","intent_id":"cabin_nav_to"}
|
||||
{"text":"把空调设到22度","intent_id":"cabin_set_ac"}
|
||||
{"text":"车里温度调成24度","intent_id":"cabin_set_ac"}
|
||||
{"text":"冷气开到20度","intent_id":"cabin_set_ac"}
|
||||
{"text":"空调给我调低一点到21度","intent_id":"cabin_set_ac"}
|
||||
{"text":"温度改成23度","intent_id":"cabin_set_ac"}
|
||||
{"text":"播放一首轻音乐","intent_id":"cabin_play_music"}
|
||||
{"text":"来点周杰伦的歌","intent_id":"cabin_play_music"}
|
||||
{"text":"放一首夜曲","intent_id":"cabin_play_music"}
|
||||
{"text":"我想听摇滚","intent_id":"cabin_play_music"}
|
||||
{"text":"给我播点古典音乐","intent_id":"cabin_play_music"}
|
||||
118
intelligent_cabin/app/data/bert_intent_train.jsonl
Normal file
118
intelligent_cabin/app/data/bert_intent_train.jsonl
Normal file
@@ -0,0 +1,118 @@
|
||||
{"text":"帮我查一下订单A123456","intent_id":"cs_query_order"}
|
||||
{"text":"查询订单A765432现在到哪一步了","intent_id":"cs_query_order"}
|
||||
{"text":"我的订单A998877是什么状态","intent_id":"cs_query_order"}
|
||||
{"text":"帮我看看订单A556677","intent_id":"cs_query_order"}
|
||||
{"text":"查下订单A112233","intent_id":"cs_query_order"}
|
||||
{"text":"订单A456789现在怎么样","intent_id":"cs_query_order"}
|
||||
{"text":"我想查订单A333444","intent_id":"cs_query_order"}
|
||||
{"text":"看看订单A909090进度","intent_id":"cs_query_order"}
|
||||
{"text":"订单A202501状态","intent_id":"cs_query_order"}
|
||||
{"text":"帮我确认一下订单A808001","intent_id":"cs_query_order"}
|
||||
{"text":"查物流A123456","intent_id":"cs_query_logistics"}
|
||||
{"text":"帮我看订单A765432物流","intent_id":"cs_query_logistics"}
|
||||
{"text":"快递A998877到哪了","intent_id":"cs_query_logistics"}
|
||||
{"text":"物流A556677现在什么情况","intent_id":"cs_query_logistics"}
|
||||
{"text":"查一下快递单A112233","intent_id":"cs_query_logistics"}
|
||||
{"text":"看看A456789物流信息","intent_id":"cs_query_logistics"}
|
||||
{"text":"订单A333444的快递到了吗","intent_id":"cs_query_logistics"}
|
||||
{"text":"帮我查查A909090配送进度","intent_id":"cs_query_logistics"}
|
||||
{"text":"物流单号A202501现在在哪里","intent_id":"cs_query_logistics"}
|
||||
{"text":"我的订单A808001物流到了哪","intent_id":"cs_query_logistics"}
|
||||
{"text":"帮我取消订单A123456","intent_id":"cs_cancel_order"}
|
||||
{"text":"取消一下A765432这个订单","intent_id":"cs_cancel_order"}
|
||||
{"text":"撤销订单A998877","intent_id":"cs_cancel_order"}
|
||||
{"text":"订单A556677我不要了","intent_id":"cs_cancel_order"}
|
||||
{"text":"把A112233这个订单取消掉","intent_id":"cs_cancel_order"}
|
||||
{"text":"我想退掉并取消A456789","intent_id":"cs_cancel_order"}
|
||||
{"text":"帮我撤回订单A333444","intent_id":"cs_cancel_order"}
|
||||
{"text":"A909090别发了直接取消","intent_id":"cs_cancel_order"}
|
||||
{"text":"取消订单号A202501","intent_id":"cs_cancel_order"}
|
||||
{"text":"把A808001撤销了","intent_id":"cs_cancel_order"}
|
||||
{"text":"帮我转人工客服","intent_id":"cs_transfer_human"}
|
||||
{"text":"我要人工服务","intent_id":"cs_transfer_human"}
|
||||
{"text":"接人工","intent_id":"cs_transfer_human"}
|
||||
{"text":"帮我联系人工客服","intent_id":"cs_transfer_human"}
|
||||
{"text":"转接人工处理","intent_id":"cs_transfer_human"}
|
||||
{"text":"这个问题我要找人工","intent_id":"cs_transfer_human"}
|
||||
{"text":"给我人工坐席","intent_id":"cs_transfer_human"}
|
||||
{"text":"不要机器人了转人工","intent_id":"cs_transfer_human"}
|
||||
{"text":"请给我人工客服","intent_id":"cs_transfer_human"}
|
||||
{"text":"帮我找真人客服","intent_id":"cs_transfer_human"}
|
||||
{"text":"导航去公司","intent_id":"cabin_nav_to"}
|
||||
{"text":"带我去机场","intent_id":"cabin_nav_to"}
|
||||
{"text":"去虹桥火车站","intent_id":"cabin_nav_to"}
|
||||
{"text":"导航到世纪大道","intent_id":"cabin_nav_to"}
|
||||
{"text":"帮我开车去陆家嘴","intent_id":"cabin_nav_to"}
|
||||
{"text":"去最近的充电站","intent_id":"cabin_nav_to"}
|
||||
{"text":"带我到南京东路","intent_id":"cabin_nav_to"}
|
||||
{"text":"导航去浦东机场","intent_id":"cabin_nav_to"}
|
||||
{"text":"去静安寺","intent_id":"cabin_nav_to"}
|
||||
{"text":"我要去公司园区","intent_id":"cabin_nav_to"}
|
||||
{"text":"把空调调到22度","intent_id":"cabin_set_ac"}
|
||||
{"text":"空调设成24度","intent_id":"cabin_set_ac"}
|
||||
{"text":"温度调低到20度","intent_id":"cabin_set_ac"}
|
||||
{"text":"车里空调开到23度","intent_id":"cabin_set_ac"}
|
||||
{"text":"帮我把车内温度设置为21度","intent_id":"cabin_set_ac"}
|
||||
{"text":"空调打到25度","intent_id":"cabin_set_ac"}
|
||||
{"text":"把冷气调成19度","intent_id":"cabin_set_ac"}
|
||||
{"text":"把空调温度改为26度","intent_id":"cabin_set_ac"}
|
||||
{"text":"车内设到18度","intent_id":"cabin_set_ac"}
|
||||
{"text":"温度给我设成22度","intent_id":"cabin_set_ac"}
|
||||
{"text":"播放轻音乐","intent_id":"cabin_play_music"}
|
||||
{"text":"来点歌","intent_id":"cabin_play_music"}
|
||||
{"text":"帮我放首歌","intent_id":"cabin_play_music"}
|
||||
{"text":"我想听周杰伦","intent_id":"cabin_play_music"}
|
||||
{"text":"来一首夜曲","intent_id":"cabin_play_music"}
|
||||
{"text":"放点摇滚","intent_id":"cabin_play_music"}
|
||||
{"text":"听一下古典音乐","intent_id":"cabin_play_music"}
|
||||
{"text":"给我播轻音乐","intent_id":"cabin_play_music"}
|
||||
{"text":"来点民谣","intent_id":"cabin_play_music"}
|
||||
{"text":"播放默认歌单","intent_id":"cabin_play_music"}
|
||||
{"text":"订单A310001现在受理了吗","intent_id":"cs_query_order"}
|
||||
{"text":"帮我看下A310002这单进展","intent_id":"cs_query_order"}
|
||||
{"text":"A310003这个订单处理到哪了","intent_id":"cs_query_order"}
|
||||
{"text":"查询一下订单A310004当前状态","intent_id":"cs_query_order"}
|
||||
{"text":"订单A310005现在啥情况","intent_id":"cs_query_order"}
|
||||
{"text":"帮我确认A310006订单有没有在处理","intent_id":"cs_query_order"}
|
||||
{"text":"A310007这笔订单最新进度是什么","intent_id":"cs_query_order"}
|
||||
{"text":"看看订单A310008有没有结果","intent_id":"cs_query_order"}
|
||||
{"text":"订单A320001物流到哪了","intent_id":"cs_query_logistics"}
|
||||
{"text":"帮我查A320002这单配送进度","intent_id":"cs_query_logistics"}
|
||||
{"text":"A320003快递现在运到哪里了","intent_id":"cs_query_logistics"}
|
||||
{"text":"看一下订单A320004有没有派件","intent_id":"cs_query_logistics"}
|
||||
{"text":"A320005物流轨迹更新了吗","intent_id":"cs_query_logistics"}
|
||||
{"text":"帮我追踪一下A320006运输状态","intent_id":"cs_query_logistics"}
|
||||
{"text":"订单A320007快件到哪一步了","intent_id":"cs_query_logistics"}
|
||||
{"text":"A320008这单现在送到哪儿了","intent_id":"cs_query_logistics"}
|
||||
{"text":"查一下A320009的派送信息","intent_id":"cs_query_logistics"}
|
||||
{"text":"A320010物流有没有新动态","intent_id":"cs_query_logistics"}
|
||||
{"text":"订单A330001不要了,帮我撤单","intent_id":"cs_cancel_order"}
|
||||
{"text":"A330002这单别发了直接取消","intent_id":"cs_cancel_order"}
|
||||
{"text":"把订单A330003停掉吧","intent_id":"cs_cancel_order"}
|
||||
{"text":"A330004这个订单我不想要了","intent_id":"cs_cancel_order"}
|
||||
{"text":"订单A330005给我撤回","intent_id":"cs_cancel_order"}
|
||||
{"text":"把A330006这笔订单关掉","intent_id":"cs_cancel_order"}
|
||||
{"text":"A330007先别发货了,取消掉","intent_id":"cs_cancel_order"}
|
||||
{"text":"帮我把订单A330008作废","intent_id":"cs_cancel_order"}
|
||||
{"text":"A330009这单不要了","intent_id":"cs_cancel_order"}
|
||||
{"text":"订单A330010撤单处理","intent_id":"cs_cancel_order"}
|
||||
{"text":"这个问题给我人工跟进","intent_id":"cs_transfer_human"}
|
||||
{"text":"安排真人客服接手","intent_id":"cs_transfer_human"}
|
||||
{"text":"机器人处理不了,转人工","intent_id":"cs_transfer_human"}
|
||||
{"text":"帮我叫个客服专员","intent_id":"cs_transfer_human"}
|
||||
{"text":"我要人工来处理这事","intent_id":"cs_transfer_human"}
|
||||
{"text":"规划路线去虹桥机场T2","intent_id":"cabin_nav_to"}
|
||||
{"text":"直接开去公司停车场","intent_id":"cabin_nav_to"}
|
||||
{"text":"给我导到最近的充电站","intent_id":"cabin_nav_to"}
|
||||
{"text":"徐家汇怎么走,导航一下","intent_id":"cabin_nav_to"}
|
||||
{"text":"出发去外滩","intent_id":"cabin_nav_to"}
|
||||
{"text":"把车内温度设为20度","intent_id":"cabin_set_ac"}
|
||||
{"text":"空调温度改到21度","intent_id":"cabin_set_ac"}
|
||||
{"text":"冷气帮我调到22度","intent_id":"cabin_set_ac"}
|
||||
{"text":"舱内调成23度","intent_id":"cabin_set_ac"}
|
||||
{"text":"给我把温度定在24度","intent_id":"cabin_set_ac"}
|
||||
{"text":"随机放点轻音乐","intent_id":"cabin_play_music"}
|
||||
{"text":"帮我播首晴天","intent_id":"cabin_play_music"}
|
||||
{"text":"来点适合开车听的民谣","intent_id":"cabin_play_music"}
|
||||
{"text":"打开音乐,放夜曲","intent_id":"cabin_play_music"}
|
||||
{"text":"给我放一些爵士","intent_id":"cabin_play_music"}
|
||||
352
intelligent_cabin/app/data/intents.json
Normal file
352
intelligent_cabin/app/data/intents.json
Normal file
@@ -0,0 +1,352 @@
|
||||
[
|
||||
{
|
||||
"intent_id": "cs_query_order",
|
||||
"plugin_id": "plugin.order.query",
|
||||
"domain": "customer_service",
|
||||
"risk_level": "low",
|
||||
"required_slots": ["order_id"],
|
||||
"ask_templates": {
|
||||
"order_id": "请提供订单号。"
|
||||
},
|
||||
"keywords": ["查询订单", "查订单", "订单状态"],
|
||||
"examples": ["帮我查一下订单", "我的订单到哪一步了", "查下订单状态"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cs_query_logistics",
|
||||
"plugin_id": "plugin.logistics.query",
|
||||
"domain": "customer_service",
|
||||
"risk_level": "low",
|
||||
"required_slots": ["order_id"],
|
||||
"ask_templates": {
|
||||
"order_id": "请提供订单号。"
|
||||
},
|
||||
"keywords": ["查物流", "物流", "快递"],
|
||||
"examples": ["帮我查一下快递", "看看物流到哪了", "快递什么时候到"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cs_cancel_order",
|
||||
"plugin_id": "plugin.order.cancel",
|
||||
"domain": "customer_service",
|
||||
"risk_level": "medium",
|
||||
"required_slots": ["order_id"],
|
||||
"ask_templates": {
|
||||
"order_id": "请提供要取消的订单号。"
|
||||
},
|
||||
"keywords": ["取消订单", "撤销订单"],
|
||||
"examples": ["帮我取消这个订单", "我不想要了取消吧", "撤销刚才的订单"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cs_transfer_human",
|
||||
"plugin_id": "plugin.service.transfer_human",
|
||||
"domain": "customer_service",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["转人工", "人工客服", "联系客服"],
|
||||
"examples": ["我要人工客服", "帮我转人工", "联系客服"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_nav_cancel",
|
||||
"plugin_id": "plugin.cabin.navigation.cancel",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["取消导航", "结束导航", "停止导航"],
|
||||
"examples": ["把导航关掉", "退出导航", "别导航了"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_nav_to",
|
||||
"plugin_id": "plugin.cabin.navigation",
|
||||
"domain": "cabin",
|
||||
"risk_level": "medium",
|
||||
"required_slots": ["destination"],
|
||||
"ask_templates": {
|
||||
"destination": "请告诉我要导航去哪里。"
|
||||
},
|
||||
"keywords": ["导航去", "导航到", "带我去"],
|
||||
"examples": ["导航去公司", "带我去机场", "导航到虹桥火车站"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_ac_on",
|
||||
"plugin_id": "plugin.cabin.ac.on",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开空调", "开启空调", "空调打开"],
|
||||
"examples": ["把空调打开", "开空调", "启动空调"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_ac_off",
|
||||
"plugin_id": "plugin.cabin.ac.off",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["关闭空调", "关掉空调", "空调关闭"],
|
||||
"examples": ["把空调关掉", "别吹空调了", "空调先关了"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_set_ac",
|
||||
"plugin_id": "plugin.cabin.ac_control",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": ["temperature"],
|
||||
"ask_templates": {
|
||||
"temperature": "请告诉我要设置多少度。"
|
||||
},
|
||||
"keywords": ["空调调到", "温度设成", "设成多少度"],
|
||||
"examples": ["把空调调到22度", "温度设成24度", "空调调到20度"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_fan_up",
|
||||
"plugin_id": "plugin.cabin.fan.up",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["调大风量", "风量大一点", "风量调高"],
|
||||
"examples": ["把风量调大一点", "空调风再大一点", "风量开大些"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_fan_down",
|
||||
"plugin_id": "plugin.cabin.fan.down",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["调小风量", "风量小一点", "风量调低"],
|
||||
"examples": ["把风量调小一点", "空调风太大了", "风量关小些"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_defog_front_on",
|
||||
"plugin_id": "plugin.cabin.defog.front_on",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开前挡除雾", "前挡风除雾", "前窗除雾"],
|
||||
"examples": ["帮我打开前挡除雾", "前挡风玻璃起雾了", "开一下前挡除雾"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_defog_rear_on",
|
||||
"plugin_id": "plugin.cabin.defog.rear_on",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开后挡除雾", "后挡风除雾", "后窗除雾"],
|
||||
"examples": ["帮我打开后挡除雾", "后挡风玻璃起雾了", "开一下后挡除雾"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_window_open",
|
||||
"plugin_id": "plugin.cabin.window.open",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开车窗", "开车窗", "车窗打开"],
|
||||
"examples": ["把车窗打开", "帮我开一下车窗", "打开一点车窗"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_window_close",
|
||||
"plugin_id": "plugin.cabin.window.close",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["关闭车窗", "关车窗", "车窗关上"],
|
||||
"examples": ["把车窗关上", "帮我关一下车窗", "车窗全部关闭"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_sunroof_open",
|
||||
"plugin_id": "plugin.cabin.sunroof.open",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开天窗", "开天窗", "天窗打开"],
|
||||
"examples": ["把天窗打开", "帮我开一下天窗", "天窗打开一点"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_sunroof_close",
|
||||
"plugin_id": "plugin.cabin.sunroof.close",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["关闭天窗", "关天窗", "天窗关上"],
|
||||
"examples": ["把天窗关上", "帮我关一下天窗", "关闭全景天窗"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_lock_doors",
|
||||
"plugin_id": "plugin.cabin.doors.lock",
|
||||
"domain": "cabin",
|
||||
"risk_level": "medium",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["锁车门", "锁门", "车门锁上"],
|
||||
"examples": ["帮我锁车", "把车门锁上", "全部车门上锁"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_unlock_doors",
|
||||
"plugin_id": "plugin.cabin.doors.unlock",
|
||||
"domain": "cabin",
|
||||
"risk_level": "medium",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["解锁车门", "开锁", "车门解锁"],
|
||||
"examples": ["帮我解锁车门", "把车门打开锁", "全部车门解锁"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_play_music",
|
||||
"plugin_id": "plugin.cabin.music_play",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["播放音乐", "来点音乐", "放首歌"],
|
||||
"examples": ["播放轻音乐", "来点歌", "帮我放首歌"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_pause_music",
|
||||
"plugin_id": "plugin.cabin.music.pause",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["暂停音乐", "暂停播放", "音乐暂停"],
|
||||
"examples": ["把音乐暂停", "先别放了", "暂停当前歌曲"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_next_track",
|
||||
"plugin_id": "plugin.cabin.music.next",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["下一首", "切下一首", "换首歌"],
|
||||
"examples": ["帮我切到下一首", "下一首歌", "换一首歌"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_previous_track",
|
||||
"plugin_id": "plugin.cabin.music.previous",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["上一首", "切上一首", "返回上一首"],
|
||||
"examples": ["帮我切到上一首", "上一首歌", "返回刚才那首歌"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_volume_up",
|
||||
"plugin_id": "plugin.cabin.volume.up",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["调大音量", "音量大一点", "音量调高"],
|
||||
"examples": ["把音量调大一点", "声音太小了", "音量开大些"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_volume_down",
|
||||
"plugin_id": "plugin.cabin.volume.down",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["调小音量", "音量小一点", "音量调低"],
|
||||
"examples": ["把音量调小一点", "声音太大了", "音量关小些"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_volume_mute",
|
||||
"plugin_id": "plugin.cabin.volume.mute",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["静音", "关闭声音", "音量静音"],
|
||||
"examples": ["把声音关掉", "先静音", "音响静音"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_lights_on",
|
||||
"plugin_id": "plugin.cabin.lights.on",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开车灯", "开灯", "车灯打开"],
|
||||
"examples": ["把车灯打开", "帮我开一下灯", "打开大灯"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_lights_off",
|
||||
"plugin_id": "plugin.cabin.lights.off",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["关闭车灯", "关灯", "车灯关闭"],
|
||||
"examples": ["把车灯关掉", "帮我关一下灯", "关闭大灯"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_seat_heat_on",
|
||||
"plugin_id": "plugin.cabin.seat_heat.on",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开座椅加热", "开座椅加热", "座椅加热打开"],
|
||||
"examples": ["把座椅加热打开", "帮我开一下座椅加热", "打开主驾座椅加热"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_seat_heat_off",
|
||||
"plugin_id": "plugin.cabin.seat_heat.off",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["关闭座椅加热", "关座椅加热", "座椅加热关闭"],
|
||||
"examples": ["把座椅加热关掉", "帮我关一下座椅加热", "关闭主驾座椅加热"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_mirror_fold",
|
||||
"plugin_id": "plugin.cabin.mirror.fold",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["折叠后视镜", "收起后视镜", "后视镜折叠"],
|
||||
"examples": ["把后视镜折叠起来", "帮我收起后视镜", "折叠两侧后视镜"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_mirror_unfold",
|
||||
"plugin_id": "plugin.cabin.mirror.unfold",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["展开后视镜", "打开后视镜", "后视镜展开"],
|
||||
"examples": ["把后视镜展开", "帮我打开后视镜", "展开两侧后视镜"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_wiper_on",
|
||||
"plugin_id": "plugin.cabin.wiper.on",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["打开雨刷", "开雨刷", "雨刷启动"],
|
||||
"examples": ["把雨刷打开", "帮我开一下雨刷", "启动雨刮器"]
|
||||
},
|
||||
{
|
||||
"intent_id": "cabin_wiper_off",
|
||||
"plugin_id": "plugin.cabin.wiper.off",
|
||||
"domain": "cabin",
|
||||
"risk_level": "low",
|
||||
"required_slots": [],
|
||||
"ask_templates": {},
|
||||
"keywords": ["关闭雨刷", "关雨刷", "雨刷停止"],
|
||||
"examples": ["把雨刷关掉", "帮我关一下雨刷", "停止雨刮器"]
|
||||
}
|
||||
]
|
||||
10
intelligent_cabin/app/data/joint_nlu_eval.jsonl
Normal file
10
intelligent_cabin/app/data/joint_nlu_eval.jsonl
Normal file
@@ -0,0 +1,10 @@
|
||||
{"text":"把空调设到21度","intent_id":"cabin_set_ac","slots":[{"slot_name":"temperature","value":"21度","start":6,"end":9}]}
|
||||
{"text":"导航到虹桥机场","intent_id":"cabin_nav_to","slots":[{"slot_name":"destination","value":"虹桥机场","start":3,"end":7}]}
|
||||
{"text":"来首稻香","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"稻香","start":2,"end":4}]}
|
||||
{"text":"放点摇滚","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"摇滚","start":2,"end":4}]}
|
||||
{"text":"查一下订单A700001现在什么状态","intent_id":"cs_query_order","slots":[{"slot_name":"order_id","value":"A700001","start":5,"end":12}]}
|
||||
{"text":"帮我查A900005物流进度","intent_id":"cs_query_logistics","slots":[{"slot_name":"order_id","value":"A900005","start":4,"end":11}]}
|
||||
{"text":"撤销订单A202501","intent_id":"cs_cancel_order","slots":[{"slot_name":"order_id","value":"A202501","start":4,"end":11}]}
|
||||
{"text":"把车窗打开","intent_id":"cabin_window_open","slots":[]}
|
||||
{"text":"把音乐暂停","intent_id":"cabin_pause_music","slots":[]}
|
||||
{"text":"帮我锁车","intent_id":"cabin_lock_doors","slots":[]}
|
||||
43
intelligent_cabin/app/data/joint_nlu_eval_independent.jsonl
Normal file
43
intelligent_cabin/app/data/joint_nlu_eval_independent.jsonl
Normal file
@@ -0,0 +1,43 @@
|
||||
{"text":"把空调调到22度","expected_intent_id":"cabin_set_ac","expected_slots":{"temperature":22},"category":"slot_temperature"}
|
||||
{"text":"空调给我调到20度","expected_intent_id":"cabin_set_ac","expected_slots":{"temperature":20},"category":"slot_temperature"}
|
||||
{"text":"车里温度设成24度","expected_intent_id":"cabin_set_ac","expected_slots":{"temperature":24},"category":"slot_temperature"}
|
||||
{"text":"把温度打到21度","expected_intent_id":"cabin_set_ac","expected_slots":{"temperature":21},"category":"slot_temperature"}
|
||||
{"text":"导航去公司停车场","expected_intent_id":"cabin_nav_to","expected_slots":{"destination":"公司停车场"},"category":"slot_destination"}
|
||||
{"text":"带我去浦东机场","expected_intent_id":"cabin_nav_to","expected_slots":{"destination":"浦东机场"},"category":"slot_destination"}
|
||||
{"text":"导航到南京东路","expected_intent_id":"cabin_nav_to","expected_slots":{"destination":"南京东路"},"category":"slot_destination"}
|
||||
{"text":"去虹桥机场","expected_intent_id":"cabin_nav_to","expected_slots":{"destination":"虹桥机场"},"category":"slot_destination"}
|
||||
{"text":"查一下订单A123456","expected_intent_id":"cs_query_order","expected_slots":{"order_id":"A123456"},"category":"slot_order"}
|
||||
{"text":"帮我看看订单A808001","expected_intent_id":"cs_query_order","expected_slots":{"order_id":"A808001"},"category":"slot_order"}
|
||||
{"text":"快递A998877到哪了","expected_intent_id":"cs_query_logistics","expected_slots":{"order_id":"A998877"},"category":"slot_order"}
|
||||
{"text":"取消订单A556677","expected_intent_id":"cs_cancel_order","expected_slots":{"order_id":"A556677"},"category":"slot_order"}
|
||||
{"text":"来一首青花瓷","expected_intent_id":"cabin_play_music","expected_slots":{"song":"青花瓷"},"category":"slot_music"}
|
||||
{"text":"播放夜的第七章","expected_intent_id":"cabin_play_music","expected_slots":{"song":"夜的第七章"},"category":"slot_music"}
|
||||
{"text":"来点爵士","expected_intent_id":"cabin_play_music","expected_slots":{"genre":"爵士"},"category":"slot_music"}
|
||||
{"text":"放点摇滚","expected_intent_id":"cabin_play_music","expected_slots":{"genre":"摇滚"},"category":"slot_music"}
|
||||
{"text":"给我播点民谣","expected_intent_id":"cabin_play_music","expected_slots":{"genre":"民谣"},"category":"slot_music"}
|
||||
{"text":"把车窗打开","expected_intent_id":"cabin_window_open","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把车窗关上","expected_intent_id":"cabin_window_close","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把天窗打开","expected_intent_id":"cabin_sunroof_open","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把天窗合上","expected_intent_id":"cabin_sunroof_close","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把空调打开","expected_intent_id":"cabin_ac_on","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把空调关掉","expected_intent_id":"cabin_ac_off","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把风量调大一点","expected_intent_id":"cabin_fan_up","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"风太大了,往小调一点","expected_intent_id":"cabin_fan_down","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把音乐暂停","expected_intent_id":"cabin_pause_music","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"帮我切到下一首","expected_intent_id":"cabin_next_track","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"切回上一首","expected_intent_id":"cabin_previous_track","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"先静音","expected_intent_id":"cabin_volume_mute","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把音量调大一点","expected_intent_id":"cabin_volume_up","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把音量调小一点","expected_intent_id":"cabin_volume_down","expected_slots":{},"category":"no_slot_control"}
|
||||
{"text":"把后视镜收起来","expected_intent_id":"cabin_mirror_fold","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"把镜子展开","expected_intent_id":"cabin_mirror_unfold","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"锁车门","expected_intent_id":"cabin_lock_doors","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"把车门解锁","expected_intent_id":"cabin_unlock_doors","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"路线别导了","expected_intent_id":"cabin_nav_cancel","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"音乐停一下","expected_intent_id":"cabin_pause_music","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"雨刮关掉","expected_intent_id":"cabin_wiper_off","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"把雨刮打开","expected_intent_id":"cabin_wiper_on","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"把左前窗降一点","expected_intent_id":"cabin_window_open","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"给我透个气","expected_intent_id":"cabin_window_open","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"风别太小","expected_intent_id":"cabin_fan_up","expected_slots":{},"category":"failure_replay"}
|
||||
{"text":"要是太慢就转人工","expected_intent_id":"cs_transfer_human","expected_slots":{},"category":"failure_replay"}
|
||||
12
intelligent_cabin/app/data/joint_nlu_multilabel_eval.jsonl
Normal file
12
intelligent_cabin/app/data/joint_nlu_multilabel_eval.jsonl
Normal file
@@ -0,0 +1,12 @@
|
||||
{"text":"打开车窗和空调","intent_ids":["cabin_window_open","cabin_ac_on"],"slots":[]}
|
||||
{"text":"导航去公司再放点轻音乐","intent_ids":["cabin_nav_to","cabin_play_music"],"slots":[{"slot_name":"destination","value":"公司","start":3,"end":5},{"slot_name":"genre","value":"轻音乐","start":8,"end":11}]}
|
||||
{"text":"把空调调到22度并播放夜曲","intent_ids":["cabin_set_ac","cabin_play_music"],"slots":[{"slot_name":"temperature","value":"22度","start":6,"end":9},{"slot_name":"song","value":"夜曲","start":12,"end":14}]}
|
||||
{"text":"开空调,关窗,再来点民谣","intent_ids":["cabin_ac_on","cabin_window_close","cabin_play_music"],"slots":[{"slot_name":"genre","value":"民谣","start":11,"end":13}]}
|
||||
{"text":"查一下订单A700001,如果还没发货就取消","intent_ids":["cs_query_order","cs_cancel_order"],"slots":[{"slot_name":"order_id","value":"A700001","start":5,"end":12}]}
|
||||
{"text":"查下A808001物流,没到就转人工","intent_ids":["cs_query_logistics","cs_transfer_human"],"slots":[{"slot_name":"order_id","value":"A808001","start":2,"end":9}]}
|
||||
{"text":"把风量调大一点,再把窗户打开","intent_ids":["cabin_fan_up","cabin_window_open"],"slots":[]}
|
||||
{"text":"透透气,再来一首黄昏","intent_ids":["cabin_window_open","cabin_play_music"],"slots":[{"slot_name":"song","value":"黄昏","start":9,"end":11}]}
|
||||
{"text":"导航到虹桥机场,空调也打开","intent_ids":["cabin_nav_to","cabin_ac_on"],"slots":[{"slot_name":"destination","value":"虹桥机场","start":3,"end":7}]}
|
||||
{"text":"后视镜收起来,再锁车门","intent_ids":["cabin_mirror_fold","cabin_lock_doors"],"slots":[]}
|
||||
{"text":"雨刮关掉并打开车窗","intent_ids":["cabin_wiper_off","cabin_window_open"],"slots":[]}
|
||||
{"text":"来点音乐,再把温度设成21度","intent_ids":["cabin_play_music","cabin_set_ac"],"slots":[{"slot_name":"temperature","value":"21度","start":12,"end":15}]}
|
||||
27
intelligent_cabin/app/data/joint_nlu_seed.jsonl
Normal file
27
intelligent_cabin/app/data/joint_nlu_seed.jsonl
Normal file
@@ -0,0 +1,27 @@
|
||||
{"text":"把空调调到22度","intent_id":"cabin_set_ac","slots":[{"slot_name":"temperature","value":"22度","start":6,"end":9}]}
|
||||
{"text":"空调给我调到20度","intent_id":"cabin_set_ac","slots":[{"slot_name":"temperature","value":"20度","start":7,"end":10}]}
|
||||
{"text":"车里温度设成24度","intent_id":"cabin_set_ac","slots":[{"slot_name":"temperature","value":"24度","start":7,"end":10}]}
|
||||
{"text":"导航去公司停车场","intent_id":"cabin_nav_to","slots":[{"slot_name":"destination","value":"公司停车场","start":3,"end":8}]}
|
||||
{"text":"带我去浦东机场","intent_id":"cabin_nav_to","slots":[{"slot_name":"destination","value":"浦东机场","start":3,"end":7}]}
|
||||
{"text":"导航到南京东路","intent_id":"cabin_nav_to","slots":[{"slot_name":"destination","value":"南京东路","start":3,"end":7}]}
|
||||
{"text":"播放夜曲","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"夜曲","start":2,"end":4}]}
|
||||
{"text":"来一首青花瓷","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"青花瓷","start":3,"end":6}]}
|
||||
{"text":"放一首晴天","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"晴天","start":3,"end":5}]}
|
||||
{"text":"来一首告白气球","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"告白气球","start":3,"end":7}]}
|
||||
{"text":"播放稻香","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"稻香","start":2,"end":4}]}
|
||||
{"text":"帮我播首夜的第七章","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"夜的第七章","start":4,"end":9}]}
|
||||
{"text":"给我来一首晴天","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"晴天","start":5,"end":7}]}
|
||||
{"text":"车里放首稻香","intent_id":"cabin_play_music","slots":[{"slot_name":"song","value":"稻香","start":4,"end":6}]}
|
||||
{"text":"播放轻音乐","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"轻音乐","start":2,"end":5}]}
|
||||
{"text":"来点爵士","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"爵士","start":2,"end":4}]}
|
||||
{"text":"给我播点民谣","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"民谣","start":4,"end":6}]}
|
||||
{"text":"随机放点流行","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"流行","start":4,"end":6}]}
|
||||
{"text":"来点古典音乐","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"古典","start":2,"end":4}]}
|
||||
{"text":"车里放点摇滚","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"摇滚","start":4,"end":6}]}
|
||||
{"text":"给我来点儿歌","intent_id":"cabin_play_music","slots":[{"slot_name":"genre","value":"儿歌","start":4,"end":6}]}
|
||||
{"text":"查一下订单A123456","intent_id":"cs_query_order","slots":[{"slot_name":"order_id","value":"A123456","start":5,"end":12}]}
|
||||
{"text":"帮我看看订单A808001","intent_id":"cs_query_order","slots":[{"slot_name":"order_id","value":"A808001","start":6,"end":13}]}
|
||||
{"text":"快递A998877到哪了","intent_id":"cs_query_logistics","slots":[{"slot_name":"order_id","value":"A998877","start":2,"end":9}]}
|
||||
{"text":"帮我查A202501物流","intent_id":"cs_query_logistics","slots":[{"slot_name":"order_id","value":"A202501","start":4,"end":11}]}
|
||||
{"text":"取消订单A556677","intent_id":"cs_cancel_order","slots":[{"slot_name":"order_id","value":"A556677","start":4,"end":11}]}
|
||||
{"text":"把A112233这个订单取消掉","intent_id":"cs_cancel_order","slots":[{"slot_name":"order_id","value":"A112233","start":1,"end":8}]}
|
||||
151
intelligent_cabin/app/main.py
Normal file
151
intelligent_cabin/app/main.py
Normal file
@@ -0,0 +1,151 @@
|
||||
import json
|
||||
from concurrent.futures import ThreadPoolExecutor, TimeoutError
|
||||
from pathlib import Path
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import FileResponse, StreamingResponse
|
||||
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.bootstrap import build_agent_service_with_runtime, build_intent_registry
|
||||
from app.schemas.chat import ChatRequest, ChatResponse, FillSlotsRequest
|
||||
from app.schemas.demo import DemoRuntimeConfig, DemoRuntimeUpdateRequest
|
||||
|
||||
app = FastAPI(title=settings.app_name)
|
||||
|
||||
# CORS:允许 Canvas 前端跨域调用
|
||||
# 生产环境请将 allow_origins 替换为实际前端域名
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
demo_html_path = Path(__file__).parent / "static" / "demo.html"
|
||||
chat_stream_executor = ThreadPoolExecutor(max_workers=8)
|
||||
|
||||
runtime_config = DemoRuntimeConfig(
|
||||
matcher_pipeline=settings.matcher_pipeline,
|
||||
classifier_backend=settings.classifier_backend,
|
||||
session_backend=settings.session_backend,
|
||||
slot_extractor_backend=settings.slot_extractor_backend,
|
||||
planner_backend=settings.planner_backend,
|
||||
planner_model_name=settings.planner_model_name,
|
||||
)
|
||||
agent_service = build_agent_service_with_runtime(
|
||||
matcher_pipeline=runtime_config.matcher_pipeline,
|
||||
classifier_backend=runtime_config.classifier_backend,
|
||||
session_backend=runtime_config.session_backend,
|
||||
)
|
||||
intent_registry = build_intent_registry()
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> dict[str, str]:
|
||||
return {"status": "ok", "env": settings.app_env}
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@app.get("/demo")
|
||||
def demo() -> FileResponse:
|
||||
return FileResponse(demo_html_path)
|
||||
|
||||
|
||||
@app.post("/api/v1/agent/chat", response_model=ChatResponse)
|
||||
def chat(request: ChatRequest) -> ChatResponse:
|
||||
return agent_service.handle_chat(request)
|
||||
|
||||
|
||||
@app.post("/api/v1/agent/chat-stream")
|
||||
def chat_stream(request: ChatRequest) -> StreamingResponse:
|
||||
def stream():
|
||||
future = chat_stream_executor.submit(agent_service.handle_chat, request)
|
||||
try:
|
||||
response = future.result(timeout=1.0)
|
||||
except TimeoutError:
|
||||
ack = {
|
||||
"type": "ack",
|
||||
"reply_text": "好的,正在处理中,请稍等一下。",
|
||||
"status": "processing",
|
||||
"trace_id": uuid4().hex,
|
||||
}
|
||||
yield json.dumps(ack, ensure_ascii=False) + "\n"
|
||||
try:
|
||||
response = future.result()
|
||||
except Exception as exc: # pragma: no cover - stream error fallback
|
||||
payload = {
|
||||
"type": "error",
|
||||
"message": str(exc),
|
||||
}
|
||||
yield json.dumps(payload, ensure_ascii=False) + "\n"
|
||||
return
|
||||
except Exception as exc: # pragma: no cover - stream error fallback
|
||||
payload = {
|
||||
"type": "error",
|
||||
"message": str(exc),
|
||||
}
|
||||
yield json.dumps(payload, ensure_ascii=False) + "\n"
|
||||
return
|
||||
|
||||
try:
|
||||
payload = {
|
||||
"type": "final",
|
||||
"data": response.model_dump(mode="json"),
|
||||
}
|
||||
yield json.dumps(payload, ensure_ascii=False) + "\n"
|
||||
except Exception as exc: # pragma: no cover - stream error fallback
|
||||
payload = {
|
||||
"type": "error",
|
||||
"message": str(exc),
|
||||
}
|
||||
yield json.dumps(payload, ensure_ascii=False) + "\n"
|
||||
|
||||
return StreamingResponse(stream(), media_type="application/x-ndjson")
|
||||
|
||||
|
||||
@app.post("/api/v1/agent/fill-slots", response_model=ChatResponse)
|
||||
def fill_slots(request: FillSlotsRequest) -> ChatResponse:
|
||||
return agent_service.handle_fill_slots(request)
|
||||
|
||||
|
||||
@app.get("/api/v1/intents")
|
||||
def list_intents() -> list[dict[str, object]]:
|
||||
return [intent.model_dump() for intent in intent_registry.list()]
|
||||
|
||||
|
||||
@app.get("/api/v1/demo/runtime", response_model=DemoRuntimeConfig)
|
||||
def get_demo_runtime() -> DemoRuntimeConfig:
|
||||
return runtime_config
|
||||
|
||||
|
||||
@app.post("/api/v1/demo/runtime", response_model=DemoRuntimeConfig)
|
||||
def update_demo_runtime(request: DemoRuntimeUpdateRequest) -> DemoRuntimeConfig:
|
||||
global agent_service, runtime_config
|
||||
|
||||
matcher_stages = [stage.strip() for stage in request.matcher_pipeline.split(",") if stage.strip()]
|
||||
if matcher_stages != ["classifier"]:
|
||||
raise HTTPException(status_code=400, detail="Only classifier matcher pipeline is supported in bert-first mode")
|
||||
|
||||
try:
|
||||
next_service = build_agent_service_with_runtime(
|
||||
matcher_pipeline=request.matcher_pipeline,
|
||||
classifier_backend=request.classifier_backend,
|
||||
session_backend=request.session_backend,
|
||||
)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
agent_service = next_service
|
||||
runtime_config = DemoRuntimeConfig(
|
||||
matcher_pipeline=request.matcher_pipeline,
|
||||
classifier_backend=request.classifier_backend,
|
||||
session_backend=request.session_backend,
|
||||
slot_extractor_backend=settings.slot_extractor_backend,
|
||||
planner_backend=settings.planner_backend,
|
||||
planner_model_name=settings.planner_model_name,
|
||||
)
|
||||
return runtime_config
|
||||
1
intelligent_cabin/app/plugins/__init__.py
Normal file
1
intelligent_cabin/app/plugins/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Plugin adapters for the agent service."""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
intelligent_cabin/app/plugins/__pycache__/base.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/plugins/__pycache__/base.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/plugins/__pycache__/base.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/plugins/__pycache__/base.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/plugins/__pycache__/base.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/plugins/__pycache__/base.cpython-313.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/plugins/__pycache__/mock.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/plugins/__pycache__/mock.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/plugins/__pycache__/mock.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/plugins/__pycache__/mock.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/plugins/__pycache__/mock.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/plugins/__pycache__/mock.cpython-313.pyc
Normal file
Binary file not shown.
27
intelligent_cabin/app/plugins/base.py
Normal file
27
intelligent_cabin/app/plugins/base.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
PluginHandler = Callable[[dict[str, Any]], dict[str, Any]]
|
||||
|
||||
|
||||
class PluginRegistry:
|
||||
def __init__(self) -> None:
|
||||
self._handlers: dict[str, PluginHandler] = {}
|
||||
|
||||
def register(self, plugin_id: str, handler: PluginHandler) -> None:
|
||||
self._handlers[plugin_id] = handler
|
||||
|
||||
def execute(self, plugin_id: str, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
handler = self._handlers.get(plugin_id)
|
||||
if handler is None:
|
||||
return {
|
||||
"success": False,
|
||||
"message": f"插件 {plugin_id} 未注册。",
|
||||
"data": {"plugin_id": plugin_id, "slots": slots},
|
||||
}
|
||||
return handler(slots)
|
||||
|
||||
def registered_plugins(self) -> list[str]:
|
||||
return sorted(self._handlers.keys())
|
||||
216
intelligent_cabin/app/plugins/mock.py
Normal file
216
intelligent_cabin/app/plugins/mock.py
Normal file
@@ -0,0 +1,216 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from app.plugins.base import PluginRegistry
|
||||
|
||||
|
||||
class MockPluginExecutor:
|
||||
def register(self, registry: PluginRegistry) -> PluginRegistry:
|
||||
registry.register("plugin.order.query", self._query_order)
|
||||
registry.register("plugin.logistics.query", self._query_logistics)
|
||||
registry.register("plugin.order.cancel", self._cancel_order)
|
||||
registry.register("plugin.service.transfer_human", self._transfer_human)
|
||||
registry.register("plugin.cabin.navigation.cancel", self._navigate_cancel)
|
||||
registry.register("plugin.cabin.navigation", self._navigate)
|
||||
registry.register("plugin.cabin.ac.on", self._ac_on)
|
||||
registry.register("plugin.cabin.ac.off", self._ac_off)
|
||||
registry.register("plugin.cabin.ac_control", self._set_ac)
|
||||
registry.register("plugin.cabin.fan.up", self._fan_up)
|
||||
registry.register("plugin.cabin.fan.down", self._fan_down)
|
||||
registry.register("plugin.cabin.defog.front_on", self._defog_front_on)
|
||||
registry.register("plugin.cabin.defog.rear_on", self._defog_rear_on)
|
||||
registry.register("plugin.cabin.window.open", self._window_open)
|
||||
registry.register("plugin.cabin.window.close", self._window_close)
|
||||
registry.register("plugin.cabin.sunroof.open", self._sunroof_open)
|
||||
registry.register("plugin.cabin.sunroof.close", self._sunroof_close)
|
||||
registry.register("plugin.cabin.doors.lock", self._lock_doors)
|
||||
registry.register("plugin.cabin.doors.unlock", self._unlock_doors)
|
||||
registry.register("plugin.cabin.music_play", self._play_music)
|
||||
registry.register("plugin.cabin.music.pause", self._pause_music)
|
||||
registry.register("plugin.cabin.music.next", self._next_track)
|
||||
registry.register("plugin.cabin.music.previous", self._previous_track)
|
||||
registry.register("plugin.cabin.volume.up", self._volume_up)
|
||||
registry.register("plugin.cabin.volume.down", self._volume_down)
|
||||
registry.register("plugin.cabin.volume.mute", self._volume_mute)
|
||||
registry.register("plugin.cabin.lights.on", self._lights_on)
|
||||
registry.register("plugin.cabin.lights.off", self._lights_off)
|
||||
registry.register("plugin.cabin.seat_heat.on", self._seat_heat_on)
|
||||
registry.register("plugin.cabin.seat_heat.off", self._seat_heat_off)
|
||||
registry.register("plugin.cabin.mirror.fold", self._mirror_fold)
|
||||
registry.register("plugin.cabin.mirror.unfold", self._mirror_unfold)
|
||||
registry.register("plugin.cabin.wiper.on", self._wiper_on)
|
||||
registry.register("plugin.cabin.wiper.off", self._wiper_off)
|
||||
return registry
|
||||
|
||||
def _query_order(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"订单 {slots['order_id']} 当前待发货。",
|
||||
"data": {"order_status": "pending_shipment"},
|
||||
}
|
||||
|
||||
def _query_logistics(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"订单 {slots['order_id']} 最新物流状态为运输中。",
|
||||
"data": {"logistics_status": "shipping"},
|
||||
}
|
||||
|
||||
def _cancel_order(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"订单 {slots['order_id']} 已取消。",
|
||||
"data": {"cancel_status": "cancelled"},
|
||||
}
|
||||
|
||||
def _transfer_human(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": "已为你转接人工客服,请稍候。",
|
||||
"data": {"queue_no": "A12", "reason": slots.get("reason", "用户请求")},
|
||||
}
|
||||
|
||||
def _navigate(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"已开始导航到 {slots['destination']}。",
|
||||
"data": {"route_id": "route_001", "destination": slots["destination"]},
|
||||
}
|
||||
|
||||
def _navigate_cancel(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已结束当前导航。", {"navigation": "stopped"})
|
||||
|
||||
def _ac_on(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开空调。", {"power": "on"})
|
||||
|
||||
def _ac_off(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已关闭空调。", {"power": "off"})
|
||||
|
||||
def _set_ac(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"已将空调调到 {slots['temperature']} 度。",
|
||||
"data": {"temperature": slots["temperature"]},
|
||||
}
|
||||
|
||||
def _fan_up(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已调大风量。", {"fan": "up"})
|
||||
|
||||
def _fan_down(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已调小风量。", {"fan": "down"})
|
||||
|
||||
def _defog_front_on(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开前挡除雾。", {"defog": "front_on"})
|
||||
|
||||
def _defog_rear_on(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开后挡除雾。", {"defog": "rear_on"})
|
||||
|
||||
def _window_open(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开车窗。", {"window": "open"})
|
||||
|
||||
def _window_close(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已关闭车窗。", {"window": "close"})
|
||||
|
||||
def _sunroof_open(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开天窗。", {"sunroof": "open"})
|
||||
|
||||
def _sunroof_close(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已关闭天窗。", {"sunroof": "close"})
|
||||
|
||||
def _lock_doors(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已锁定车门。", {"doors": "locked"})
|
||||
|
||||
def _unlock_doors(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已解锁车门。", {"doors": "unlocked"})
|
||||
|
||||
def _play_music(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
target = slots.get("song") or slots.get("genre") or "默认歌单"
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"正在播放 {target}。",
|
||||
"data": {"play_target": target},
|
||||
}
|
||||
|
||||
def _pause_music(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已暂停播放。", {"music": "paused"})
|
||||
|
||||
def _next_track(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已切到下一首。", {"music": "next"})
|
||||
|
||||
def _previous_track(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已切到上一首。", {"music": "previous"})
|
||||
|
||||
def _volume_up(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已调大音量。", {"volume": "up"})
|
||||
|
||||
def _volume_down(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已调小音量。", {"volume": "down"})
|
||||
|
||||
def _volume_mute(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已静音。", {"volume": "mute"})
|
||||
|
||||
def _lights_on(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开车灯。", {"lights": "on"})
|
||||
|
||||
def _lights_off(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已关闭车灯。", {"lights": "off"})
|
||||
|
||||
def _seat_heat_on(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开座椅加热。", {"seat_heat": "on"})
|
||||
|
||||
def _seat_heat_off(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已关闭座椅加热。", {"seat_heat": "off"})
|
||||
|
||||
def _mirror_fold(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已折叠后视镜。", {"mirror": "folded"})
|
||||
|
||||
def _mirror_unfold(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已展开后视镜。", {"mirror": "unfolded"})
|
||||
|
||||
def _wiper_on(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已打开雨刷。", {"wiper": "on"})
|
||||
|
||||
def _wiper_off(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
_ = slots
|
||||
return self._simple_action("好的,已关闭雨刷。", {"wiper": "off"})
|
||||
|
||||
def _fallback(self, slots: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": "已接收请求,当前使用 mock 插件返回成功结果。",
|
||||
"data": slots,
|
||||
}
|
||||
|
||||
def _simple_action(self, message: str, data: dict[str, Any]) -> dict[str, Any]:
|
||||
return {
|
||||
"success": True,
|
||||
"message": message,
|
||||
"data": data,
|
||||
}
|
||||
1
intelligent_cabin/app/schemas/__init__.py
Normal file
1
intelligent_cabin/app/schemas/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Pydantic schemas for the agent service."""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/chat.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/chat.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/chat.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/chat.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/chat.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/chat.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/debug.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/debug.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/debug.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/debug.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/debug.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/debug.cpython-313.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/demo.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/demo.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/demo.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/demo.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/demo.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/demo.cpython-313.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/intent.cpython-311.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/intent.cpython-311.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/intent.cpython-312.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/intent.cpython-312.pyc
Normal file
Binary file not shown.
BIN
intelligent_cabin/app/schemas/__pycache__/intent.cpython-313.pyc
Normal file
BIN
intelligent_cabin/app/schemas/__pycache__/intent.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
46
intelligent_cabin/app/schemas/chat.py
Normal file
46
intelligent_cabin/app/schemas/chat.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.schemas.debug import RoutingDebug
|
||||
from app.schemas.workflow import Workflow
|
||||
|
||||
|
||||
class ChatRequest(BaseModel):
|
||||
session_id: str
|
||||
user_id: str
|
||||
channel: str = "app"
|
||||
input_text: str
|
||||
input_type: Literal["text", "voice"] = "text"
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class FillSlotsRequest(BaseModel):
|
||||
session_id: str
|
||||
user_id: str
|
||||
input_text: str
|
||||
|
||||
|
||||
class ChatResponse(BaseModel):
|
||||
session_id: str
|
||||
reply_type: Literal["text", "ask_slot", "ask_confirmation", "workflow_result", "fallback", "clarify", "reject"] = "text"
|
||||
reply_text: str
|
||||
intent: str | None = None
|
||||
domain: str | None = None
|
||||
decision: str | None = None
|
||||
decision_reason: str | None = None
|
||||
status: str
|
||||
pending_slots: list[str] = Field(default_factory=list)
|
||||
filled_slots: dict[str, Any] = Field(default_factory=dict)
|
||||
workflow: Workflow | None = None
|
||||
routing_debug: RoutingDebug | None = None
|
||||
first_response_latency_ms: float | None = None
|
||||
total_latency_ms: float | None = None
|
||||
processing_breakdown: dict[str, float] = Field(default_factory=dict)
|
||||
trace_id: str
|
||||
# ── 知识库查询结果(LLM function call 命中时填充)──────────────────────────
|
||||
knowledge_doc_id: str | None = None # 知识文档 ID(MD 文件名)
|
||||
knowledge_doc_title: str | None = None # 知识文档标题
|
||||
knowledge_content: str | None = None # 完整 MD 正文,供前端渲染知识卡片
|
||||
135
intelligent_cabin/app/schemas/configuration.py
Normal file
135
intelligent_cabin/app/schemas/configuration.py
Normal file
@@ -0,0 +1,135 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.schemas.intent import IntentDefinition
|
||||
|
||||
|
||||
class ActionDefinition(BaseModel):
|
||||
action_id: str
|
||||
plugin_id: str
|
||||
risk_level: Literal["low", "medium", "high"] = "low"
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class DomainIntentDefinition(BaseModel):
|
||||
intent_id: str
|
||||
domain: str
|
||||
action_id: str | None = None
|
||||
plugin_id: str | None = None
|
||||
risk_level: Literal["low", "medium", "high"] | None = None
|
||||
label: str | None = None
|
||||
required_slots: list[str] = Field(default_factory=list)
|
||||
ask_templates: dict[str, str] = Field(default_factory=dict)
|
||||
keywords: list[str] = Field(default_factory=list)
|
||||
examples: list[str] = Field(default_factory=list)
|
||||
|
||||
def to_intent_definition(self, actions: dict[str, ActionDefinition]) -> IntentDefinition:
|
||||
plugin_id = self.plugin_id
|
||||
risk_level = self.risk_level
|
||||
if self.action_id:
|
||||
action = actions[self.action_id]
|
||||
plugin_id = action.plugin_id
|
||||
if risk_level is None:
|
||||
risk_level = action.risk_level
|
||||
if not plugin_id:
|
||||
raise ValueError(f"intent {self.intent_id} is missing plugin_id/action_id mapping")
|
||||
return IntentDefinition(
|
||||
intent_id=self.intent_id,
|
||||
plugin_id=plugin_id,
|
||||
domain=self.domain,
|
||||
risk_level=risk_level or "low",
|
||||
required_slots=self.required_slots,
|
||||
ask_templates=self.ask_templates,
|
||||
keywords=self.keywords,
|
||||
examples=self.examples,
|
||||
)
|
||||
|
||||
|
||||
class DomainConfig(BaseModel):
|
||||
intents: list[DomainIntentDefinition] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ActionsConfig(BaseModel):
|
||||
actions: list[ActionDefinition] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ResponsesConfig(BaseModel):
|
||||
templates: dict[str, str] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class FormDefinition(BaseModel):
|
||||
intent_id: str
|
||||
required_slots: list[str] = Field(default_factory=list)
|
||||
ask_templates: dict[str, str] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class FormsConfig(BaseModel):
|
||||
forms: list[FormDefinition] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ConfirmationRuleConfig(BaseModel):
|
||||
positive_tokens: list[str] = Field(default_factory=list)
|
||||
negative_tokens: list[str] = Field(default_factory=list)
|
||||
required_intents: list[str] = Field(default_factory=list)
|
||||
required_risk_levels: list[Literal["low", "medium", "high"]] = Field(default_factory=list)
|
||||
|
||||
|
||||
class StopRuleConfig(BaseModel):
|
||||
phrases: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class DialogRulesConfig(BaseModel):
|
||||
stop: StopRuleConfig = Field(default_factory=StopRuleConfig)
|
||||
confirmation: ConfirmationRuleConfig = Field(default_factory=ConfirmationRuleConfig)
|
||||
|
||||
|
||||
class DialogActPatternDefinition(BaseModel):
|
||||
act_id: str
|
||||
phrases: list[str] = Field(default_factory=list)
|
||||
# 正则列表:文本匹配任意一个则命中该 act(用于数字类 inform)
|
||||
numeric_patterns: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class DialogActsConfig(BaseModel):
|
||||
acts: list[DialogActPatternDefinition] = Field(default_factory=list)
|
||||
|
||||
|
||||
# ── Context Rewrite Config ────────────────────────────────────────────────────
|
||||
|
||||
class ParamContextDefinition(BaseModel):
|
||||
"""一类可相对调节参数的上下文改写规则。"""
|
||||
intent_ids: list[str]
|
||||
slot_name: str
|
||||
unit: str = ""
|
||||
step: int | float = 1
|
||||
min_value: int | float = 0
|
||||
max_value: int | float = 9999
|
||||
default_value: int | float = 0
|
||||
up_phrases: list[str] = Field(default_factory=list)
|
||||
down_phrases: list[str] = Field(default_factory=list)
|
||||
rewrite_template: str = "{value}"
|
||||
|
||||
|
||||
class ContextRewriteConfig(BaseModel):
|
||||
param_contexts: list[ParamContextDefinition] = Field(default_factory=list)
|
||||
|
||||
|
||||
class WorkflowTemplateStepOverride(BaseModel):
|
||||
depends_on: list[int] = Field(default_factory=list)
|
||||
condition: dict[str, Any] = Field(default_factory=dict)
|
||||
requires_confirmation: bool = False
|
||||
|
||||
|
||||
class WorkflowTemplateDefinition(BaseModel):
|
||||
template_id: str
|
||||
workflow_type: Literal["sequence", "conditional", "parallel"] = "sequence"
|
||||
intent_sequence: list[str] = Field(default_factory=list)
|
||||
step_overrides: list[WorkflowTemplateStepOverride] = Field(default_factory=list)
|
||||
trigger_keywords: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class WorkflowTemplatesConfig(BaseModel):
|
||||
templates: list[WorkflowTemplateDefinition] = Field(default_factory=list)
|
||||
42
intelligent_cabin/app/schemas/debug.py
Normal file
42
intelligent_cabin/app/schemas/debug.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class IntentCandidate(BaseModel):
|
||||
intent_id: str
|
||||
score: float = 0.0
|
||||
reason: str | None = None
|
||||
model_name: str | None = None
|
||||
raw_label: str | None = None
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class MatcherStageDebug(BaseModel):
|
||||
stage: str
|
||||
accepted: bool = False
|
||||
selected_intent: str | None = None
|
||||
score: float = 0.0
|
||||
elapsed_ms: float | None = None
|
||||
reason: str | None = None
|
||||
model_name: str | None = None
|
||||
backend: str | None = None
|
||||
fallback_used: bool = False
|
||||
raw_label: str | None = None
|
||||
error_message: str | None = None
|
||||
metadata: dict[str, Any] = Field(default_factory=dict)
|
||||
candidates: list[IntentCandidate] = Field(default_factory=list)
|
||||
|
||||
|
||||
class RoutingDebug(BaseModel):
|
||||
selected_intent: str | None = None
|
||||
matched_stage: str | None = None
|
||||
decision: str = "reject"
|
||||
decision_reason: str | None = None
|
||||
confidence_grade: str | None = None
|
||||
total_match_latency_ms: float | None = None
|
||||
unknown_detected: bool = False
|
||||
extracted_slots: dict[str, Any] = Field(default_factory=dict)
|
||||
stages: list[MatcherStageDebug] = Field(default_factory=list)
|
||||
20
intelligent_cabin/app/schemas/demo.py
Normal file
20
intelligent_cabin/app/schemas/demo.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class DemoRuntimeConfig(BaseModel):
|
||||
matcher_pipeline: Literal["classifier"]
|
||||
classifier_backend: Literal["mock", "bert", "remote", "joint_bert"]
|
||||
session_backend: Literal["memory", "redis"]
|
||||
slot_extractor_backend: str
|
||||
planner_backend: str
|
||||
planner_model_name: str
|
||||
|
||||
|
||||
class DemoRuntimeUpdateRequest(BaseModel):
|
||||
matcher_pipeline: Literal["classifier"] = Field(default="classifier")
|
||||
classifier_backend: Literal["mock", "bert", "remote", "joint_bert"]
|
||||
session_backend: Literal["memory", "redis"]
|
||||
16
intelligent_cabin/app/schemas/intent.py
Normal file
16
intelligent_cabin/app/schemas/intent.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class IntentDefinition(BaseModel):
|
||||
intent_id: str
|
||||
plugin_id: str
|
||||
domain: str
|
||||
risk_level: Literal["low", "medium", "high"] = "low"
|
||||
required_slots: list[str] = Field(default_factory=list)
|
||||
ask_templates: dict[str, str] = Field(default_factory=dict)
|
||||
keywords: list[str] = Field(default_factory=list)
|
||||
examples: list[str] = Field(default_factory=list)
|
||||
38
intelligent_cabin/app/schemas/workflow.py
Normal file
38
intelligent_cabin/app/schemas/workflow.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class WorkflowStep(BaseModel):
|
||||
step: int
|
||||
step_id: str
|
||||
intent_id: str
|
||||
plugin_id: str
|
||||
action: str
|
||||
status: Literal["pending", "running", "completed", "failed", "skipped", "waiting_confirmation"] = "pending"
|
||||
depends_on: list[str] = Field(default_factory=list)
|
||||
slots: dict[str, Any] = Field(default_factory=dict)
|
||||
condition: dict[str, Any] = Field(default_factory=dict)
|
||||
requires_confirmation: bool = False
|
||||
timeout_ms: int = 1500
|
||||
|
||||
|
||||
class MissingSlot(BaseModel):
|
||||
slot_name: str
|
||||
ask_template: str
|
||||
priority: int = 1
|
||||
|
||||
|
||||
class Workflow(BaseModel):
|
||||
workflow_id: str
|
||||
workflow_type: Literal["single", "sequence", "conditional", "parallel"] = "single"
|
||||
domain: str
|
||||
intent_id: str
|
||||
status: Literal["ready", "waiting_slot", "waiting_confirmation", "running", "completed", "failed"] = "ready"
|
||||
risk_level: Literal["low", "medium", "high"] = "low"
|
||||
slots: dict[str, Any] = Field(default_factory=dict)
|
||||
missing_slots: list[MissingSlot] = Field(default_factory=list)
|
||||
steps: list[WorkflowStep] = Field(default_factory=list)
|
||||
meta: dict[str, Any] = Field(default_factory=dict)
|
||||
1
intelligent_cabin/app/services/__init__.py
Normal file
1
intelligent_cabin/app/services/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Application services for orchestration and session management."""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user