Rasa 模拟实现超简易医生助手(适合初学练手)
下面是一个纯 Rasa 实现的医生助手第一版项目文件内容,具备基本的“多轮问诊”流程逻辑,通过 slot 存储用户的多个症状,在最后阶段给出“模拟的诊断建议”。
PS:完成这个之后,下一步我还想在Rasa工作过程中引入大模型辅助完成对话流程。
📁 项目结构与文件内容
✅ actions/actions.py
from typing import Any, Text, Dict, List
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.events import SlotSetclass ActionAskMoreSymptoms(Action):def name(self) -> Text:return "action_ask_more_symptoms"def run(self, dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:# 获取本轮对话中所有识别到的 symptom 实体new_symptoms = tracker.get_slot("new_symptom") or []# 获取历史症状collected_symptoms = tracker.get_slot("collected_symptoms") or []if new_symptoms:# 将当前轮症状添加到历史症状列表中collected_symptoms.extend(new_symptoms)dispatcher.utter_message(text=f"已记录你的症状:{', '.join(new_symptoms)}。")else:dispatcher.utter_message(text="我没有识别到具体症状,请再描述一下。")dispatcher.utter_message(text=f"目前已记录症状:{', '.join(collected_symptoms)}。还有其他不适吗?")# 更新槽位return [SlotSet("collected_symptoms", collected_symptoms)]class ActionSimulateDiagnosis(Action):def name(self) -> Text:return "action_simulate_diagnosis"def run(self, dispatcher: CollectingDispatcher,tracker: Tracker,domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:symptoms = tracker.get_slot("collected_symptoms") or []if not symptoms:dispatcher.utter_message(text="我目前没有记录到任何症状。")else:symptom_list = ", ".join(symptoms)dispatcher.utter_message(text=f"根据你提供的症状:{symptom_list},建议进一步检查。可能为常见疾病,请就医确认。")return []
✅ data/nlu.yml
version: "3.1"nlu:- intent: greetexamples: |- 你好- 嗨- intent: report_symptomexamples: |- 我有点[头疼](symptom)- [胸闷](symptom)- 最近[恶心](symptom)- [口干](symptom)- [胸口发闷](symptom)- [头疼](symptom)- [喉咙痛](symptom)- [发烧](symptom)- [肚子疼](symptom)- [胸口闷](symptom)- [咳嗽](symptom)- 感觉[恶心](symptom)- 有点[鼻塞](symptom)- intent: denyexamples: |- 没有了- 没有其他不适- 没事了- 没有
✅ data/rules.yml
version: "3.1"rules:
- rule: 启动问诊steps:- intent: greet- action: utter_greet- rule: 用户说出症状后继续追问steps:- intent: report_symptom- action: utter_ack_symptom- action: action_ask_more_symptoms- rule: 用户否认后进入诊断steps:- intent: deny- action: action_simulate_diagnosis
✅ data/stories.yml
version: "3.1"stories:
- story: 多轮问诊并诊断steps:- intent: report_symptom- action: utter_ack_symptom- action: action_ask_more_symptoms- intent: report_symptom- action: utter_ack_symptom- action: action_ask_more_symptoms- intent: deny- action: action_simulate_diagnosis
✅ tests/test_stories.yml
version: "3.1"stories:
- story: 测试完整问诊流程steps:- user: |我头疼intent: report_symptom- action: utter_ack_symptom- action: action_ask_more_symptoms- user: |还有点咳嗽intent: report_symptom- action: utter_ack_symptom- action: action_ask_more_symptoms- user: |没有了intent: deny- action: action_simulate_diagnosis
✅ config.yml
recipe: default.v1assistant_id: 20250412-010713-concrete-weaponlanguage: zhpipeline: - name: JiebaTokenizer- name: RegexFeaturizer- name: LexicalSyntacticFeaturizer- name: CountVectorsFeaturizer- name: DIETClassifierepochs: 100- name: EntitySynonymMapper- name: FallbackClassifierthreshold: 0.4ambiguity_threshold: 0.1policies: - name: RulePolicy- name: UnexpecTEDIntentPolicy # 辅助检测用户意图偏差max_history: 5epochs: 100
✅ credentials.yml
rest:
✅ domain.yml
version: "3.1"intents:- greet- report_symptom- denyslots:new_symptom:type: listinitial_value: []influence_conversation: falsemappings:- type: from_entityentity: symptomcollected_symptoms:type: anyinitial_value: []influence_conversation: falsemappings: [] # 添加一个空的 mappings 配置entities:- symptomactions:- utter_greet- action_ask_more_symptoms- action_simulate_diagnosisresponses:utter_greet:- text: "你好,我是医生助手,请描述你的症状。"utter_ack_symptom:- text: 已记录你的症状。
✅ endpoints.yml
action_endpoint:#url: "http://localhost:5055/webhook"#action_server是之后运行action的docker容器名字url: "http://action_server:5055/webhook"
✅ 启动流程简要说明
1. 训练模型:
docker run -u $(id -u):$(id -g) -v $(pwd):/app rasa/rasa:3.6.21-full train
2. 创建一个 bridge 网络
docker network create rasa-net
然后用这个网络跑两个容器:
3.启动 action server 服务器(一个终端)
docker run --rm -u $(id -u):$(id -g) --network rasa-net -v $(pwd):/app -p 5055:5055 --name action_server rasa/rasa:3.6.21-full run actions
#--name action_server注意这里设置的容器名需要和action_endpoint里的设置匹配
4.启动对话测试 rasa shell(另一个终端)
docker run --rm -it -u $(id -u):$(id -g) --network rasa-net -v $(pwd):/app rasa/rasa:3.6.21-full shell
这样两个容器在同一个网络里,localhost:5055
就能通了。
博主私人备注:
用于检测nul
docker run --rm -it -u $(id -u):$(id -g) --network rasa-net -v $(pwd):/app rasa/rasa:3.6.21-full shell nlu