原文:
towardsdatascience.com/how-to-develop-an-effective-ai-powered-legal-assistant-096550746987
在这篇文章中,我描述了如何创建一个用于搜索挪威最高法院判决的应用程序。这个应用程序是一个有用的工具,可以快速了解不同主题的判决,如果你想要了解最高法院对特定主题的立场,这尤其有趣。如果你想要了解更多关于创建高级 AI 搜索以查找文档的信息,这也可能很有趣。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ab54a66b59453780d470b4b1c208e440.png
在这篇文章中,我将向您展示我是如何制作一个强大的法律助理的。图片由 ChatGPT 提供。
你可以在此处访问本文中开发的应用程序:
Rettsavgjørelser
动机
我写这篇文章的动机是描述使用最新语言模型技术创建法律助理的过程。这个工具有可能为从事研究课题的律师节省大量时间。未来,我计划扩展其应用范围,包括检索相关法律、相关行为者的已发布法律意见等。这样就可以作为一个完整的工具,帮助律师快速了解他们所考虑的主题。在当今世界,律师事务所的初级律师花费大量时间收集所有这些信息。我的目标是开发一个使这个过程更加有效的应用程序,让律师有更多时间从事其他任务。这不仅可以帮助律师事务所更有效地帮助客户,还可以节省客户的钱,因为律师的时间被更有效地利用了。
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.loom.com%2Fembed%2Ffc6f1872f48542f89e3c5964410e1848&display_name=Loom&url=https%3A%2F%2Fwww.loom.com%2Fshare%2Ffc6f1872f48542f89e3c5964410e1848%3Fsid%3Dc60e0efe-16d7-4dc4-bfba-98e4db5faea7&image=https%3A%2F%2Fcdn.loom.com%2Fsessions%2Fthumbnails%2Ffc6f1872f48542f89e3c5964410e1848-8007040bc82e5cf4.gif&type=text%2Fhtml&schema=loom
我已经撰写了描述此应用程序开发子过程的文章。在如何为您的 ML 应用程序创建吸引人的前端中,我详细介绍了我是如何使用 v0 语言模型制作网站的。我还为 Towards Data Science 撰写了一篇更技术性的关于开发此网站搜索部分的描述,链接见下文。
实现 Anthropic 的上下文检索以获得强大的 RAG 性能
考虑到这一部分深入探讨了创建此应用程序的技术部分,本文将更多地关注创建应用程序的高级部分。
目录
· 动机 · 目录 · 检索数据 · 在 AWS 中存储数据 · 开发 RAG 搜索 · 创建网站 · 部署 ∘ 托管前端 ∘ 托管后端 · 我遇到的问题 · 结论
检索数据
本应用程序使用的数据是挪威最高法院的法院裁决。您可以在最高法院网站上找到法院裁决。然而,这里的问题是很难找到特定的裁决,因为网站上的搜索功能非常基础。这也是我决定创建我的应用程序的原因之一。我还添加了一个免责声明,说明这些法院裁决在挪威由于是[公共利益文件](https://www.kopinor.no/opphavsrett/opphavsrett-p-123#:~:text=Av%20hensyn%20til%20allmennhetens%20behov,vern%20(%C3%A5ndsverklovens%20%C2%A7%2014)而被免于版权法(这意味着它们可以用于商业目的)。
为了创建我的应用程序,我需要提取网站上可用的所有法院裁决。自然,一个选择是手动提取所有法院裁决,但这将花费很多时间。相反,我创建了一个网络爬虫,可以从网站上提取每个案例。这是可以接受的,因为如上所述,法院裁决免于版权法。由于网站上 URL 的格式非常可预测,因此爬取是可能的。它们都从一个基础 URL 开始:
www.domstol.no/no/hoyesterett/avgjorelser/
您可以通过在 URL 的末尾添加年份来找到每年的案例(请注意,格式有时会略有变化,因此您必须检查不同的可能格式)
www.domstol.no/no/hoyesterett/avgjorelser/avgjorelser-2024/www.domstol.no/no/hoyesterett/avgjorelser/2023/www.domstol.no/no/hoyesterett/avgjorelser/2022/等
对于每个这些链接,您可以从网站上提取所有链接,其中每个链接都包含一个法院裁决。例如,从 2022 年,您可以提取
www.domstol.no/no/hoyesterett/avgjorelser/2022/hoyesterett—sivil/HR-2022-2479-A/www.domstol.no/no/hoyesterett/avgjorelser/2022/hoyesterett—sivil/HR-2022-2469-A/www.domstol.no/no/hoyesterett/avgjorelser/2022/hoyesterett—sivil/HR-2022-2484-A/
然后,您可以进入这些链接中的每一个,提取法院裁决的内容。我决定抓取以下信息
标题
唯一的案件编号(例如HR-2022–2469。案件的唯一标识符)
文本主体
包含完整法院裁决的 PDF 链接
要提取这些信息,您必须检查网站,找到不同信息存储的位置,然后使用像 Selenium 这样的包来提取内容。请注意,页面内容是动态的,因此您必须使用像 Selenium 这样的包来提取内容(仅使用 BeautifulSoup 提取 HTML 是不起作用的)
在 AWS 中存储数据
在提取了我需要的所有数据之后,我必须将其存储在某个地方。由于我之前有与 AWS 合作的经验,并且在那里获得了一些信用额度,我决定选择 AWS。我的应用程序架构如下所示:
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/09d8737f84513a1ce1da0f659547f531.png
我的应用架构。我有一个爬虫,用于获取数据。这些数据被发送到两个地方。1. 原始数据直接发送到 AWS 桶下的“extracted info”前缀下。2. 数据被发送到一个 lambda 函数,该函数创建数据块(这个 lambda 函数在爬虫提取数据并上传后自动触发)。这将从用于 RAG 搜索的原始文本中创建数据块。数据块中的文本存储在 AWS 桶中,并为文本分配一个唯一标识符(因为你不希望在 Pinecone 中存储文本)。嵌入的数据块向量与唯一标识符一起存储在 Pinecone 中,以便你可以从 AWS 桶中提取文本。当前端用户进行查询时,查询被发送到后端端点,该端点提示 Pinecone 并检索相关的法院判决。图片由作者提供。
我首先有一个爬虫,用于提取我需要的数据(最高法院的判决)。这些数据直接发送到 AWS 桶,并存储在“extracted info”前缀下。数据还被发送到一个 lambda 函数,该函数创建数据块。我已经设置这个 lambda 函数,每当上传一个新的文件(新的法院判决)时就会触发。这些数据块中的文本存储在 AWS 桶下的“chunks”前缀下,并附带一个唯一标识符。数据块文本嵌入和唯一标识符也存储在 Pinecone 中,作为向量数据库使用。用户可以在前端输入一个问题(提示)。这个提示被发送到后端端点,该端点处理并发送到 Pinecone。Pinecone 提取与提示最相关的数据块,然后后端将最相关的法院判决返回到前端。
开发 RAG 搜索
我之前已经写了一篇深入的文章,讲述了我是如何为这个应用创建 RAG 搜索的《如何为强大的 RAG 性能实现人类学上下文检索》,所以在这里我将提供一个更高级的解释。当我检索一个法院判决时,我会将其分割成不同的数据块。这些数据块存储在 Pinecone 中,这是一个向量数据库。这个向量数据库允许你存储文本的嵌入。每当用户在前端提问时,这个问题就会被嵌入。向量数据库将这个嵌入与存储在其内的所有嵌入进行比较。输出是数据库中存储的最相关的 K 个数据块(其中 K 是一个用户定义的变量)。
给定最相关的数据块,我接着找到这些数据块存储在 AWS 桶中的法院判决。我可以找到这些法院判决,因为数据块是带有唯一标识符存储的,我使用这个标识符在 AWS 桶中找到法院判决。然后,这些法院判决被返回到前端。
除了提供用户问题的来源外,我还提供问题的答案。这个答案是使用 GPT-4o 语言模型生成的。语言模型使用用户的提问进行提示,然后提供不同的法院判决作为来源。然后,语言模型能够使用法院判决作为来源,准确回答用户的问题。语言模型经常引用它用来回答问题的不同法院判决(使用法院判决的唯一标识符)。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7574e57b486ba8116de6916a31a400ab.png
这是我的 RAG 搜索的流程。流程显示了如何从语料库中创建块,然后在用户查询时检索它们。然后,从 BM25 和向量数据库中检索到的 Top K 块被组合起来,为 GPT 提供上下文以响应用户查询。图由作者提供。
创建网站
我还写了一篇更深入的关于我是如何创建这个应用程序的前端的文章。简而言之,我使用了 Vercel 的 v0 语言模型来编写大部分前端设计代码。设计前端应用程序并不是我最愿意花时间做的事情,而 v0 语言模型通过使用一些提示简单地创建一个美观的设计,为我节省了大量的时间。然而,前端的一些部分我不得不自己完成,这些部分 v0 在处理上有些吃力。其中一个是调整 API 请求以匹配后端预期的格式。另一个部分是托管前端应用程序,我使用 Vercel 来完成。我将在下一节中详细介绍这一点。
部署
托管前端
在开发前端和应用程序之后,下一步是托管它。最初,我只创建了项目的后端,并使用简单的 Streamlit 应用程序进行托管。Streamlit 是一种将产品快速投入生产、供任何人使用的方法。不幸的是,然而,Streamlit 也有一些限制。
它很慢。特别是如果一段时间内没有人使用您的应用程序,它需要冷启动,这需要更长的时间
它看起来很便宜。使用带有锁定设计的预付费网站,这种设计被许多其他网站使用,看起来很便宜,可能会吓跑一些您的产品消费者
您只能使用私有代码库托管一个项目。如果您想托管更多项目,您必须使您的代码公开可用,这通常是不受欢迎的。
因此,我决定创建我的网站,它看起来要好得多。托管前端相对简单;你将你的 next.js 项目链接到 Vercel,并将其链接到特定的分支。每次你将代码推送到这个分支时,Vercel 都会自动触发新的部署。
托管后端
托管后端更为复杂。最初,我尝试在 AWS 上以 EC2 实例的形式托管后端,以确保我总是有一个实例在运行,并能对我的用户提供快速响应时间。然而,在稍微处理了一下之后,我意识到创建一个 Lambda 函数来托管我的后端更便宜且更直接。Lambda 函数具有亚秒级的冷启动时间,这对于我的应用程序需求来说已经足够快了。然后我使用 HTTPS 端点来托管它,使其对我的前端可访问。我也可以在我的前端使用 AWS CDK,但我决定使用 HTTPS 端点访问我的 lambda 函数会更简单。
在设置好 lambda 端点之后,我的代码几乎已经准备就绪并开始运行。最后的障碍是确认 CORS(跨源资源共享),在开发 Web 应用时这通常会有点棘手。然而,在这个案例中,它并不太复杂,因为我可以在我的 AWS CDK 堆栈和 lambda 处理程序中配置所有的 CORS 设置。配置我的前端以访问后端端点后,我的应用程序已经开始运行。
我遇到的问题
在开发这个应用程序的过程中,我自然遇到了很多不同的问题。我面临的一个更具挑战性的挑战是在 AWS 上设置 EC2 实例时。在 AWS 上使用 EC2 设置 HTTPS 应用程序相对复杂。我的解决方案是,对于我的用例来说,设置 lambda 既简单又便宜。所以,最重要的经验教训是考虑你应该使用哪种服务来托管你的应用程序。我认为 lambda 通常是托管 AWS 应用程序最容易且最便宜的方式。
我遇到的另一个问题是前面提到的 CORS 问题。处理 CORS 错误是开发 Web 应用时的标准操作,解决它们可能会有点古怪。幸运的是,在这个案例中,你可以使用 AWS CDK(创建你的 lambda 函数的代码)和 lambda 处理程序函数(处理请求的函数)来配置所有的 CORS 设置。这使得使用 AWS 解决 CORS 错误变得简单得多。
此外,我目前也在努力解决响应时间的问题。在我进行测试时,用户发送查询到收到响应的时间是 8-9 秒。我认为这对于良好的用户体验来说太长了。我记得阅读过一篇关于响应时间和用户保留的 Google 研究,以及较长的响应时间会驱走很多用户。因此,我需要减少用户查询的响应时间。然而,不幸的是,响应时间受到 OpenAI API 的限制,因为几乎所有等待时间都是 OpenAI 在回答用户查询。我可以尝试几种方法来解决这个问题。一种方法是更换 API 提供商,选择一个可以提供更快响应时间的提供商。这是一个简单的更改,因为我只需要更改代码中的 API 调用,因此这是我应该尝试的事情。另一种我可以尝试的修复方法是使用不同的语言模型,它可以提供更快的响应。最后,我还可以尝试减小提示的大小,以确保更快的响应。
总体来说,创建这个应用程序遇到了许多障碍,但其中大部分可以通过 Google 搜索或提示 ChatGPT 来解决。有些挑战的解决时间比其他挑战长,但这只是作为机器学习/软件工程师工作的一部分。
结论
在这篇文章中,我讨论了我是如何创建我的法律助手应用的,该应用允许用户就挪威最高法院的裁决提出问题。这是访问大量最高法院裁决档案的有效方式,否则可能会难以导航。我首先讨论了如何检索最高法院裁决的数据,这是通过网络爬虫完成的。然后,我继续讨论了我的应用程序的架构,如何存储所有信息以及如何响应用户查询。此外,我还讨论了开发用于响应用户查询的 RAG 搜索以及我是如何制作网站的前端的。最后,我还讨论了托管应用程序的前端和后端以及我在整个项目过程中遇到的种种挑战。