|
| 1 | +#!/usr/bin/env python3 |
| 2 | +""" |
| 3 | +Discharge Note Summarizer (LangChain + HuggingFace Chat) |
| 4 | +
|
| 5 | +CDS Hooks service that summarises discharge notes using a HuggingFace |
| 6 | +chat model via LangChain (DeepSeek R1 by default). |
| 7 | +
|
| 8 | +Requirements: |
| 9 | + pip install healthchain langchain-core langchain-huggingface python-dotenv |
| 10 | + # HUGGINGFACEHUB_API_TOKEN env var required |
| 11 | +
|
| 12 | +Run: |
| 13 | + python cookbook/cds_discharge_summarizer_hf_chat.py |
| 14 | + # POST /cds/cds-services/discharge-summarizer |
| 15 | + # Docs at: http://localhost:8000/docs |
| 16 | +""" |
| 17 | + |
1 | 18 | import os |
2 | 19 | import getpass |
3 | 20 |
|
4 | | -from healthchain.gateway import HealthChainAPI, CDSHooksService |
5 | | -from healthchain.pipeline import SummarizationPipeline |
6 | | -from healthchain.models import CDSRequest, CDSResponse |
| 21 | +from dotenv import load_dotenv |
7 | 22 |
|
8 | 23 | from langchain_huggingface.llms import HuggingFaceEndpoint |
9 | 24 | from langchain_huggingface import ChatHuggingFace |
10 | 25 | from langchain_core.prompts import PromptTemplate |
11 | 26 | from langchain_core.output_parsers import StrOutputParser |
12 | 27 |
|
13 | | -from dotenv import load_dotenv |
| 28 | +from healthchain.gateway import HealthChainAPI, CDSHooksService |
| 29 | +from healthchain.pipeline import SummarizationPipeline |
| 30 | +from healthchain.models import CDSRequest, CDSResponse |
14 | 31 |
|
15 | 32 | load_dotenv() |
16 | 33 |
|
17 | 34 |
|
18 | | -if not os.getenv("HUGGINGFACEHUB_API_TOKEN"): |
19 | | - os.environ["HUGGINGFACEHUB_API_TOKEN"] = getpass.getpass("Enter your token: ") |
| 35 | +def create_chain(): |
| 36 | + if not os.getenv("HUGGINGFACEHUB_API_TOKEN"): |
| 37 | + os.environ["HUGGINGFACEHUB_API_TOKEN"] = getpass.getpass( |
| 38 | + "Enter your HuggingFace token: " |
| 39 | + ) |
20 | 40 |
|
21 | | - |
22 | | -def create_summarization_chain(): |
23 | 41 | hf = HuggingFaceEndpoint( |
24 | 42 | repo_id="deepseek-ai/DeepSeek-R1-0528", |
25 | 43 | task="text-generation", |
26 | 44 | max_new_tokens=512, |
27 | 45 | do_sample=False, |
28 | 46 | repetition_penalty=1.03, |
29 | 47 | ) |
30 | | - |
31 | 48 | model = ChatHuggingFace(llm=hf) |
32 | | - |
33 | | - template = """ |
34 | | - You are a discharge planning assistant for hospital operations. |
35 | | - Provide a concise, objective summary focusing on actionable items |
36 | | - for care coordination, including appointments, medications, and |
37 | | - follow-up instructions. Format as bullet points with no preamble.\n'''{text}''' |
38 | | - """ |
39 | | - prompt = PromptTemplate.from_template(template) |
40 | | - |
| 49 | + prompt = PromptTemplate.from_template( |
| 50 | + "You are a discharge planning assistant for hospital operations. " |
| 51 | + "Provide a concise, objective summary focusing on actionable items " |
| 52 | + "for care coordination, including appointments, medications, and " |
| 53 | + "follow-up instructions. Format as bullet points with no preamble.\n'''{text}'''" |
| 54 | + ) |
41 | 55 | return prompt | model | StrOutputParser() |
42 | 56 |
|
43 | 57 |
|
44 | | -# Create the healthcare application |
45 | | -app = HealthChainAPI( |
46 | | - title="Discharge Note Summarizer", |
47 | | - description="AI-powered discharge note summarization service", |
48 | | -) |
49 | | - |
50 | | -chain = create_summarization_chain() |
51 | | -pipeline = SummarizationPipeline.load( |
52 | | - chain, source="langchain", template_path="templates/cds_card_template.json" |
53 | | -) |
54 | | - |
55 | | -# Create CDS Hooks service |
56 | | -cds = CDSHooksService() |
| 58 | +def create_app() -> HealthChainAPI: |
| 59 | + chain = create_chain() |
| 60 | + pipeline = SummarizationPipeline.load( |
| 61 | + chain, source="langchain", template_path="templates/cds_card_template.json" |
| 62 | + ) |
| 63 | + cds = CDSHooksService() |
57 | 64 |
|
| 65 | + @cds.hook("encounter-discharge", id="discharge-summarizer") |
| 66 | + def discharge_summarizer(request: CDSRequest) -> CDSResponse: |
| 67 | + return pipeline.process_request(request) |
58 | 68 |
|
59 | | -@cds.hook("encounter-discharge", id="discharge-summarizer") |
60 | | -def discharge_summarizer(request: CDSRequest) -> CDSResponse: |
61 | | - result = pipeline.process_request(request) |
62 | | - return result |
| 69 | + app = HealthChainAPI( |
| 70 | + title="Discharge Note Summarizer", |
| 71 | + description="AI-powered discharge note summarization service", |
| 72 | + port=8000, |
| 73 | + service_type="cds-hooks", |
| 74 | + ) |
| 75 | + app.register_service(cds, path="/cds") |
| 76 | + return app |
63 | 77 |
|
64 | 78 |
|
65 | | -# Register the CDS service |
66 | | -app.register_service(cds, path="/cds") |
| 79 | +app = create_app() |
67 | 80 |
|
68 | 81 |
|
69 | 82 | if __name__ == "__main__": |
70 | | - import uvicorn |
71 | 83 | import threading |
72 | | - |
73 | 84 | from healthchain.sandbox import SandboxClient |
74 | 85 |
|
75 | | - # Start the API server in a separate thread |
76 | | - def start_api(): |
77 | | - uvicorn.run(app, port=8000) |
78 | | - |
79 | | - api_thread = threading.Thread(target=start_api, daemon=True) |
| 86 | + api_thread = threading.Thread(target=app.run, daemon=True) |
80 | 87 | api_thread.start() |
81 | 88 |
|
82 | | - # Create sandbox client and load test data |
83 | 89 | client = SandboxClient( |
84 | 90 | url="http://localhost:8000/cds/cds-services/discharge-summarizer", |
85 | 91 | workflow="encounter-discharge", |
86 | 92 | ) |
87 | | - # Load discharge notes from CSV |
88 | 93 | client.load_free_text( |
89 | 94 | csv_path="data/discharge_notes.csv", |
90 | 95 | column_name="text", |
91 | 96 | ) |
92 | | - # Send requests and get responses |
93 | 97 | responses = client.send_requests() |
94 | | - |
95 | | - # Save results |
96 | 98 | client.save_results("./output/") |
97 | 99 |
|
98 | 100 | try: |
|
0 commit comments