Spaces:
Sleeping
Sleeping
File size: 7,040 Bytes
a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 e4819a3 a8d3ea2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
import gradio as gr
import langextract as lx
import json
import os
import tempfile
import textwrap
# --- 默认模板和示例 (已更新为临床影像报告场景) ---
# 1. 默认提取指令 (Prompt)
DEFAULT_PROMPT = textwrap.dedent("""\
请从影像检查报告中,按顺序提取关键的影像学发现、涉及的解剖部位、尺寸测量、影像学特征以及阴性发现。
- 提取时必须使用报告中的确切文本。
- 不要转述或概括。
- 为每个提取的实体提供详细的属性,以增加结构化信息。""")
# 2. 默认提取示例 (Examples)
# 提供一个高质量的CT报告提取示例
DEFAULT_EXAMPLES_DICT = [
{
"text": "腹部CT平扫增强检查显示:肝脏右叶可见一大小约3.2 x 2.8 cm的低密度占位灶,边缘清晰,增强扫描后呈轻度环形强化。胰腺及双肾未见明确异常。",
"extractions": [
{
"extraction_class": "anatomy",
"extraction_text": "肝脏右叶",
"attributes": {"organ": "肝脏", "lobe": "右叶"}
},
{
"extraction_class": "size_measurement",
"extraction_text": "3.2 x 2.8 cm",
"attributes": {"value": "3.2 x 2.8", "unit": "cm"}
},
{
"extraction_class": "finding",
"extraction_text": "低密度占位灶",
"attributes": {"density": "低密度", "type": "占位灶"}
},
{
"extraction_class": "radiologic_feature",
"extraction_text": "边缘清晰",
"attributes": {"feature_type": "边缘", "description": "清晰"}
},
{
"extraction_class": "radiologic_feature",
"extraction_text": "轻度环形强化",
"attributes": {"feature_type": "增强扫描", "degree": "轻度", "pattern": "环形强化"}
},
{
"extraction_class": "normal_finding",
"extraction_text": "胰腺及双肾未见明确异常",
"attributes": {"organs": ["胰腺", "双肾"]}
}
]
}
]
# 将字典转换为格式化的 JSON 字符串,用于在界面上显示
DEFAULT_EXAMPLES_JSON = json.dumps(DEFAULT_EXAMPLES_DICT, ensure_ascii=False, indent=2)
# --- 后端处理函数 (无需修改) ---
def extract_information(api_key, prompt, examples_json, input_text):
"""
接收用户输入,调用 LangExtract 进行信息提取。
"""
# 1. 输入验证
if not api_key:
raise gr.Error("请输入您的 Google AI Studio API 密钥。")
if not prompt or not examples_json or not input_text:
raise gr.Error("提取指令、示例和源文本均不能为空。")
# 2. 解析用户输入的 JSON 示例
try:
examples_data = json.loads(examples_json)
# 将 JSON 字典转换为 LangExtract 的 ExampleData 对象
examples = [
lx.data.ExampleData(
text=ex['text'],
extractions=[
lx.data.Extraction(**extr) for extr in ex['extractions']
]
) for ex in examples_data
]
except (json.JSONDecodeError, KeyError) as e:
raise gr.Error(f"提取示例的 JSON 格式无效,请检查。错误: {e}")
# 3. 调用 LangExtract
try:
# 将 API 密钥设置到环境变量中,LangExtract 会自动读取
os.environ['LANGEXTRACT_API_KEY'] = api_key
result = lx.extract(
text_or_documents=input_text,
prompt_description=prompt,
examples=examples,
model_id="gemini-1.5-flash", # 使用速度和成本效益高的模型
)
# 将结果转换为可序列化的字典以便在 Gradio 中显示
output_for_display = {
"source_text": result.source_text,
"extractions": [ext.to_dict() for ext in result.extractions]
}
# 4. 创建可供下载的文件
with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.jsonl', encoding='utf-8') as tmp_file:
lx.io.save_annotated_documents([result], file_path=tmp_file.name)
download_path = tmp_file.name
return output_for_display, download_path
except Exception as e:
# 捕获 LangExtract 或 API 调用可能出现的任何错误
raise gr.Error(f"提取过程中发生错误: {e}")
# --- Gradio UI 界面 (无需修改) ---
with gr.Blocks(theme=gr.themes.Soft(), title="LangExtract 交互式信息提取工具") as demo:
gr.Markdown("# LangExtract 交互式信息提取工具")
gr.Markdown(
"在左侧定义您的提取规则和输入文本,然后点击“开始提取”在右侧查看结果。\n"
"您需要一个 [Google AI Studio API Key](https://aistudio.google.com/app/apikey) 才能使用此工具。"
)
with gr.Row():
# 左侧:用户输入区域
with gr.Column(scale=1):
gr.Markdown("## 1. 输入配置")
api_key_input = gr.Textbox(
label="🔑 Google AI Studio API Key",
type="password",
placeholder="在此处粘贴您的 API 密钥..."
)
gr.Markdown("## 2. 定义提取模板")
prompt_input = gr.Textbox(
label="提取指令 (Prompt)",
value=DEFAULT_PROMPT,
lines=5,
)
gr.Markdown("告诉模型您想提取什么,以及遵循什么规则。")
examples_input = gr.Code(
label="提取示例 (JSON 格式)",
value=DEFAULT_EXAMPLES_JSON,
language="json",
lines=20, # 增加了行数以更好地显示复杂的JSON
)
gr.Markdown("提供一两个高质量的示例,指导模型的输出格式。")
gr.Markdown("## 3. 输入待提取的文本")
text_input = gr.Textbox(
label="源文本",
lines=10,
placeholder="在此处粘贴您要从中提取信息的临床病历或影像报告..."
)
submit_btn = gr.Button("🚀 开始提取", variant="primary")
# 右侧:结果输出区域
with gr.Column(scale=1):
gr.Markdown("## 4. 提取结果")
json_output = gr.JSON(
label="结构化输出 (JSON)",
)
file_output = gr.File(
label="⬇️ 下载结果文件",
)
# --- 事件绑定 ---
submit_btn.click(
fn=extract_information,
inputs=[api_key_input, prompt_input, examples_input, text_input],
outputs=[json_output, file_output]
)
if __name__ == "__main__":
demo.launch() |