基于streamlit开发法律文书生成以及聊天界面

简介

    Streamlit是一个开放源代码的Python库,旨在帮助数据科学家和开发者快速构建并分享具有吸引力的交互式Web应用。这个工具特别适合那些没有前端开发背景的用户,使他们能够轻松地将数据脚本转化为可供非技术用户使用的交互式Web应用。Streamlit极大地简化了Web应用的开发流程,允许开发者将精力集中在数据处理和业务逻辑上,而非界面设计。它的核心设计理念是高效简洁,通过大幅减少模板代码的需求,让创建基于数据的应用变得异常简便。

我们作为人工智能的开发者,可以使用streamlit方便的进行前端的展示,结合后端的FastAPI接口框架,就能够达到我们所预期的效果,而且streamlit使用纯python编写,我们可以很方便的迁入我们的python代码,达到快速融合使用的效果。

页面配置,内容初始化,字体和工具导入:

st.set_page_config(
    page_title="法律文书生成",
    page_icon="🤖",
    layout='wide',
    initial_sidebar_state='collapsed'
)

st.markdown("# 法律文书生成")
st.sidebar.header("法律文书生成")
st.write(
    """这个模块提供法律文书生成功能,可以生成格式比较规范的法律文书"""
)

# @st.cache_data
import demo_tool
    

DEFAULT_SYSTEM_PROMPT = '''
你是由山东大学软件学院CLD团队开发的LecumentGEN中文法律文书大模型
'''.strip()

# 文泉驿微米黑字体的路径
font_path = '/usr/share/fonts/truetype/wqy/wqy-microhei.ttc'

pdfmetrics.registerFont(TTFont('WenQuanYi Micro Hei', font_path))

PDF生成:

​
def generate_pdf(chat_history, output_file="generated_document.pdf"):
    # 创建PDF文档的基础设置
    doc = SimpleDocTemplate(output_file, pagesize=letter)
    styles = getSampleStyleSheet()
    
    # 定义正常段落样式
    style = styles['Normal']
    style.fontName = 'WenQuanYi Micro Hei'
    style.fontSize = 12
    style.leading = 20  # 增加行间距
    style.spaceBefore = 5  # 段落前的额外空间
    style.spaceAfter = 5  # 段落后的额外空间
    style.firstLineIndent = 14  # 每段第一行缩进

    # 定义右对齐样式,用于倒数第一行和倒数第二行
    right_align_style = styles['Normal'].clone('RightAlign')
    right_align_style.alignment = 2  # 右对齐

    # 定义标题样式
    title_style = styles['Title']
    title_style.fontName = 'WenQuanYi Micro Hei'
    title_style.fontSize = 16
    title_style.leading = 24
    title_style.alignment = 1  # 居中对齐

    # 创建一个框架来定义文本的位置和大小
    frame = Frame(72, 72, 450, 700, id='normal')

​

聊天历史处理和文档内容构建

处理 chat_history 输入,根据其类型将内容分割成段落列表。

将第一段文本作为标题处理,并在标题下方添加空间。

if isinstance(chat_history, str):
    paragraphs = chat_history.split('\n\n')
elif isinstance(chat_history, list):
    paragraphs = []
    for paragraph in chat_history:
        paragraphs.extend(paragraph.split('\n\n'))
else:
    raise ValueError("Unsupported chat_history type. Must be either str or list.")
if paragraphs:
    title_text = paragraphs[0].strip()
    title = Paragraph(title_text, title_style)
    story.append(title)
    story.append(Spacer(1, 0.25 * inch))
    paragraphs = paragraphs[1:]

遍历每个段落,并根据其位置选择相应的样式(正常或右对齐),将它们转换为 Paragraph 对象并添加到内容列表 story 中。

for idx, paragraph in enumerate(paragraphs):
    lines = paragraph.split('\n')
    for line_idx, line in enumerate(lines):
        if idx >= len(paragraphs) - 2:
            p = Paragraph(line.strip(), right_align_style)
        else:
            formatted_paragraph = '  ' + line.strip()
            p = Paragraph(formatted_paragraph, style)
        story.append(p)

文档构建:

page_template = PageTemplate(frames=[frame])
doc.addPageTemplates([page_template])
doc.build(story)

页面主题构建:

它包括初始化会话状态、处理用户响应、以及提供一个交互式的用户界面来收集数据和触发事件。

如果会话状态中没有chat_history,则初始化一个空列表。这个列表用来存储用户与应用之间的互动历史。

定义了一个函数handle_response,用于将用户的输入和应用的响应保存到聊天历史中:

def handle_response(response):
    st.session_state['chat_history'].append(f"User: {prompt_text}\nBot: {response}")
    
    

# # Initialize session state for storing chat history
if 'chat_history' not in st.session_state:
    st.session_state['chat_history'] = []

# if 'generated_content' not in st.session_state:
#     st.session_state['generated_content'] = ""
    
# def update_state(key, new_value):
#     st.session_state[key] = new_value



col1, col2 = st.columns([1, 3])

if 'clear_fields' not in st.session_state:
    st.session_state['clear_fields'] = False


with col1:
    document_type = st.selectbox("选择文书类型", ["刑事判决书", "调解书"], key='document_type')

    # 根据清空标志设置输入框的默认值
    default_text = "" if st.session_state['clear_fields'] else None
    court_info = st.text_area("输入文书题目", value=default_text, key='court_info',height=50)
    case_background = st.text_area("输入案情背景", value=default_text, key='case_background')
    case_description = st.text_area("输入案情描述", value=default_text, key='case_description')
    court_staff = st.text_area("输入法庭人员", value=default_text, key='court_staff')

    generate_button = st.button("生成")
    clear_button = st.button("清空")
    
    generated_content=''
  • 使用st.columns划分页面为两列,比例为1:3。在第一列中,使用st.selectbox让用户选择文书类型,并提供多个st.text_area让用户输入文书题目、案情背景、案情描述和法庭人员等信息。提供了“生成”和“清空”按钮,分别用于生成文书和清空已输入的字段。

4. 生成与清空按钮的逻辑

if clear button代码检查是否触发了clear_button。如果是,它会在st.session_state字典中设置clear_fields键为True,然后触发应用程序的实验性重新运行。这种重新运行实际上是刷新页面的方式,可用于重置字段或根据新的会话状态值更新显示。

if clear_button:
    # 设置清空标志并重新运行以更新界面
    st.session_state['clear_fields'] = True
    st.experimental_rerun()

# public
with st.sidebar:
#     # top_p = st.slider(
#     #     'top_p', 0.0, 1.0, 0.7, step=0.01
#     # )
#     # temperature = st.slider(
#     #     'temperature', 0.0, 1.5, 0.95, step=0.01
#     # )
#     # repetition_penalty = st.slider(
#     #     'repetition_penalty', 0.0, 2.0, 1.1, step=0.01
#     # )
#     # max_new_token = st.slider(
#     #     'Output length', 5, 32000, 2000, step=1
#     # )

    cols = st.columns(2)
    export_btn = cols[0]
    clear_history = cols[1].button("Clear History", use_container_width=True)

    system_prompt = st.text_area(
        label="System Prompt (Only for chat mode)",
        height=300,
        value=get_system_prompt(document_type),
    )

这部分代码创建了一个文本区域,用于输入或显示系统提示(仅在聊天模式下使用)。get_system_prompt(document_type)函数可能用于根据不同的文档类型获取相应的系统提示文本。文本区域的高度设置为300。

generator_button

generate_button被点击时,首先将st.session_state['clear_fields']设置为False,意味着不清空字段。然后,调用get_system_prompt函数获取当前系统提示。接着,通过demo_generate.main函数生成响应,此函数接收多个参数控制文本生成的行为,如随机性(top_ptemperature),输入的提示文本,以及生成的最大新词数。

if generate_button:
    st.session_state['clear_fields'] = False  # 重置清空标志

    current_system_prompt = get_system_prompt(document_type)
    
    response = demo_generate.main(
        top_p=0.7,
        temperature=0.95,
        prompt_text=case_description,
        system_prompt=system_prompt,
        repetition_penalty=1.1,
        max_new_tokens=2000
    )
if response:
    current_time = datetime.datetime.now().strftime("%Y-%m-%d")
    generated_content = f"{court_info}\n\n{case_background}\n\n{case_description}\n\n{response}\n\n{court_staff}\n"
    # st.session_state['generated_content'] = generated_content

    st.session_state['chat_history'] = []

如果生成了响应,将当前时间格式化并与其他文本组合形成最终的生成内容。注释掉的代码可能用于保存生成的内容至会话状态,这里清空了chat_history列表,这可能用于记录交互历史。

with col2:
    st.text_area("生成内容", generated_content, height=600)

在列col2中展示生成的内容,并设置文本区域高度为600。

if generate_button:
    pdf_content = generated_content
    generate_pdf([pdf_content])

    with open("generated_document.pdf", "rb") as f:
        st.download_button(
            label="Download PDF",
            data=f,
            file_name="generated_document.pdf",
            mime="application/pdf"
        )
    st.session_state['chat_history'] = []

如果再次点击生成按钮,生成PDF文档并提供下载按钮。这部分代码还包括读取生成的PDF文件并通过下载按钮提供下载。此外,还清除了chat_history,保留生成的内容和PDF内容。

chat界面:

使用st.chat_input方法接收用户的输入,并通过demo_chat.main函数处理这些输入并生成响应。函数接收几个参数,包括输入文本、系统提示和控制生成文本的几个关键参数(如温度、惩罚因子等)。如果demo_chat.main函数返回了响应,这部分代码将调用handle_response函数来处理并可能显示这些响应。这个函数没有在代码片段中定义,可能是用户定义的或在其他部分的代码中定义。

import streamlit as st
import time
import numpy as np

st.set_page_config(page_title="法律问答", page_icon="🤔")

st.markdown("# 法律问答")
st.sidebar.header("法律问答")
st.write(
    """这个模块提供与法律相关的对话功能"""
)

import demo_chat

DEFAULT_SYSTEM_PROMPT = '''
'''.strip()

with st.sidebar:
    # top_p = st.slider(
    #     'top_p', 0.0, 1.0, 0.8, step=0.01
    # )
    # temperature = st.slider(
    #     'temperature', 0.0, 1.5, 0.95, step=0.01
    # )
    # repetition_penalty = st.slider(
    #     'repetition_penalty', 0.0, 2.0, 1.1, step=0.01
    # )
    # max_new_token = st.slider(
    #     'Output length', 5, 32000, 256, step=1
    # )

    cols = st.columns(2)
    export_btn = cols[0]
    clear_history = cols[1].button("Clear History", use_container_width=True)
    retry = export_btn.button("Retry", use_container_width=True)

    #system_prompt = st.text_area(
    #    label="System Prompt (Only for chat mode)",
    #    height=300,
    #    value=DEFAULT_SYSTEM_PROMPT,
    #)
    
# Initialize session state for storing chat history
if 'chat_history' not in st.session_state:
    st.session_state['chat_history'] = []

if clear_history or retry:
    prompt_text = ""
    st.session_state['chat_history'] = []


prompt_text = st.chat_input(
'Chat with LecumentGEN!',
key='chat_input',
)

response = demo_chat.main(
    retry=retry,
    top_p=0.8,
    temperature=0.95,
    prompt_text=prompt_text,
    system_prompt=DEFAULT_SYSTEM_PROMPT,
    repetition_penalty=1.1,
    max_new_tokens=512
)
if response:
    handle_response(response)

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值