1. 简介
我一直对法庭的紧张氛围着迷,想象自己能巧妙地应对各种复杂情况,并发表有力的结案陈词。虽然我的职业道路已将我带向其他方向,但我很高兴地告诉大家,在 AI 的帮助下,我们或许都能更接近实现那个法庭梦想。
今天,我们将深入探讨如何使用 Google 强大的 AI 工具(例如 Vertex AI、Firestore 和 Cloud Run Functions)来处理和理解法律数据、执行快速搜索,以及帮助您的假想客户(或您自己)摆脱困境。
您可能不会盘问证人,但借助我们的系统,您将能够过滤海量信息、生成清晰的摘要,并在几秒钟内呈现最相关的数据。
2. 架构
此项目侧重于使用 Google Cloud AI 工具构建法律助理,重点介绍如何处理、理解和搜索法律数据。该系统旨在过滤大量信息、生成摘要并快速呈现相关数据。法律助理的架构涉及多个关键组件:
从非结构化数据构建知识库:Google Cloud Storage (GCS) 用于存储法律文件。Firestore 是一种 NoSQL 数据库,可充当向量存储区,用于存储文档块及其对应的嵌入内容。在 Firestore 中启用向量搜索,以支持相似度搜索。当新法律文件上传到 GCS 时,Eventarc 会触发 Cloud Run 函数。此函数通过以下方式处理文档:将其拆分为多个块,并使用 Vertex AI 的文本嵌入模型为每个块生成嵌入。然后,这些嵌入会与文本块一起存储在 Firestore 中。
由 LLM 和 RAG 提供支持的应用:问答系统的核心是 ask_llm
函数,该函数使用 Langchain 库与 Vertex AI Gemini 大语言模型进行交互。它会根据用户的查询创建 HumanMessage,并包含一条 SystemMessage,指示 LLM 充当有用的法律助理。该系统采用检索增强生成 (RAG) 方法,即在回答查询之前,系统会使用 search_resource
函数从 Firestore 向量存储库中检索相关上下文。然后,将此上下文包含在 SystemMessage 中,以便 LLM 的回答基于所提供的法律信息。
该项目旨在通过使用 RAG 来摆脱 LLM 的“创造性解读”,RAG 会先从可信的法律来源检索相关信息,然后再生成答案。这样一来,系统就能根据实际法律信息生成更准确、更明智的回答。该系统使用各种 Google Cloud 服务构建而成,例如 Google Cloud Shell、Vertex AI、Firestore、Cloud Run 和 Eventarc。
3. 准备工作
在 Google Cloud 控制台的项目选择器页面上,选择或创建一个 Google Cloud 项目。确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
在 Cloud Shell IDE 中启用 Gemini Code Assist
👉 在 Google Cloud 控制台中,前往 Gemini Code Assist 工具,同意相关条款及条件,即可免费启用 Gemini Code Assist。
忽略权限设置,离开此页面。
在 Cloud Shell 编辑器中工作
👉 点击 Google Cloud 控制台顶部的“激活 Cloud Shell”(这是 Cloud Shell 窗格顶部的终端形状图标)
👉 点击“打开编辑器”按钮(铅笔图案,看起来像一个打开的文件夹)。此操作会在窗口中打开 Cloud Shell 编辑器。您会在左侧看到文件资源管理器。
👉 如图所示,点击底部状态栏中的 Cloud Code 登录按钮。按照说明对插件进行授权。如果您在状态栏中看到 Cloud Code - no project,请选择该选项,然后在下拉菜单中选择“选择 Google Cloud 项目”,然后从项目列表中选择您打算使用的 Google Cloud 项目。
👉 在云 IDE 中打开终端,
👉 在新终端中,使用以下命令验证您是否已通过身份验证,以及项目是否已设置为您的项目 ID:
gcloud auth list
👉 点击 Google Cloud 控制台顶部的激活 Cloud Shell。
gcloud config set project <YOUR_PROJECT_ID>
👉 运行以下命令以启用必要的 Google Cloud API:
gcloud services enable storage.googleapis.com \
run.googleapis.com \
artifactregistry.googleapis.com \
aiplatform.googleapis.com \
eventarc.googleapis.com \
cloudresourcemanager.googleapis.com \
firestore.googleapis.com \
cloudaicompanion.googleapis.com
在 Cloud Shell 工具栏(位于 Cloud Shell 窗格顶部)中,点击“打开编辑器”按钮(看起来像一个带有铅笔的打开的文件夹)。此操作会在窗口中打开 Cloud Shell 代码编辑器。您会在左侧看到文件资源管理器。
👉 在终端中,下载 Bootstrap 框架项目:
git clone https://github.com/weimeilin79/legal-eagle.git
可选:西班牙语版本
👉 Existe una versión alternativa en español. Utilice la siguiente instrucción para clonar la versión correcta.
git clone -b spanish https://github.com/weimeilin79/legal-eagle.git
在 Cloud Shell 终端中运行此命令后,系统会在 Cloud Shell 环境中创建一个名为 legal-eagle
的新文件夹。
4. 使用 Gemini Code Assist 编写推理应用
在本部分中,我们将重点构建法律助理的核心部分,即接收用户问题并与 AI 模型互动以生成答案的 Web 应用。我们将利用 Gemini Code Assist 帮助我们编写此推理部分的 Python 代码。
最初,我们将创建一个使用 LangChain 库直接与 Vertex AI Gemini 模型通信的 Flask 应用。此第一版将根据模型的一般知识充当有用的法律助理,但尚无法访问我们的特定法院诉讼文件。这样,我们就可以在稍后使用 RAG 增强 LLM 之前,先了解 LLM 的基准性能。
在 Cloud Code 编辑器的“探索器”窗格(通常位于左侧)中,您现在应该会看到克隆 Git 代码库时创建的文件夹 legal-eagle
。在探索器中打开项目的根文件夹。您会在其中看到一个 webapp
子文件夹,也打开该文件夹。
👉 在 Cloud Code 编辑器中修改 legal.py
文件时,您可以使用不同的方法来提示 Gemini Code Assist。
👉 将以下提示复制到 legal.py
的底部,清楚地描述您希望 Gemini Code Assist 生成的内容,点击显示的灯泡 💡 图标,然后选择 Gemini: Generate Code(确切的菜单项可能会因 Cloud Code 版本而略有不同)。
"""
Write a Python function called `ask_llm` that takes a user `query` as input. This function should use the `langchain` library to interact with a Vertex AI Gemini Large Language Model. Specifically, it should:
1. Create a `HumanMessage` object from the user's `query`.
2. Create a `ChatPromptTemplate` that includes a `SystemMessage` and the `HumanMessage`. The system message should instruct the LLM to act as a helpful assistant in a courtroom setting, aiding an attorney by providing necessary information. It should also specify that the LLM should respond in a high-energy tone, using no more than 100 words, and offer a humorous apology if it doesn't know the answer.
3. Format the `ChatPromptTemplate` with the provided messages.
4. Invoke the Vertex AI LLM with the formatted prompt using the `VertexAI` class (assuming it's already initialized elsewhere as `llm`).
5. Print the LLM's `response`.
6. Return the `response`.
7. Include error handling that prints an error message to the console and returns a user-friendly error message if any issues occur during the process. The Vertex AI model should be "gemini-2.0-flash".
"""
仔细检查生成的代码
- 它是否大致遵循了您在注释中概述的步骤?
- 它是否会创建包含
SystemMessage
和HumanMessage
的ChatPromptTemplate
? - 是否包含基本错误处理 (
try...except
)?
如果生成的代码良好且基本正确,您可以接受它(按 Tab 键或 Enter 键接受内嵌建议,或点击“接受”接受较大的代码块)。
如果您生成的代码不完全符合您的需求或存在错误,请不要担心!Gemini Code Assist 是一款辅助工具,而不是让您在第一次尝试时就编写出完美代码的工具。
修改生成的代码以对其进行优化、修正错误并更好地满足您的要求。您可以在 Code Assist 聊天面板中添加更多注释或提出具体问题,进一步提示 Gemini Code Assist。
如果您仍是 SDK 新手,可以参考以下有效示例。
👉 复制并粘贴以下代码,然后将其替换到您的 legal.py
中:
import os
import signal
import sys
import vertexai
import random
from langchain_google_vertexai import VertexAI
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.messages import HumanMessage, SystemMessage
# Connect to resourse needed from Google Cloud
llm = VertexAI(model_name="gemini-2.0-flash")
def ask_llm(query):
try:
query_message = {
"type": "text",
"text": query,
}
input_msg = HumanMessage(content=[query_message])
prompt_template = ChatPromptTemplate.from_messages(
[
SystemMessage(
content=(
"You are a helpful assistant, and you are with the attorney in a courtroom, you are helping him to win the case by providing the information he needs "
"Don't answer if you don't know the answer, just say sorry in a funny way possible"
"Use high engergy tone, don't use more than 100 words to answer"
# f"Here is some past conversation history between you and the user {relevant_history}"
# f"Here is some context that is relevant to the question {relevant_resource} that you might use"
)
),
input_msg,
]
)
prompt = prompt_template.format()
response = llm.invoke(prompt)
print(f"response: {response}")
return response
except Exception as e:
print(f"Error sending message to chatbot: {e}") # Log this error too!
return f"Unable to process your request at this time. Due to the following reason: {str(e)}"
👉 可选:西班牙语版本
Sustituye el siguiente texto como se indica: You are a helpful assistant,
to You are a helpful assistant that speaks Spanish,
接下来,创建一个函数来处理将响应用户问题的路由。
在 Cloud Shell Editor 中打开 main.py
。与您在 legal.py
中生成 ask_llm 的方式类似,使用 Gemini Code Assist 生成 Flask 路由和 ask_question 函数。在 main.py
中以注释的形式输入以下提示:(请确保在您于 if __name__ == "__main__":
启动 Flask 应用之前添加此提示)
.....
@app.route('/',methods=['GET'])
def index():
return render_template('index.html')
"""
PROMPT:
Create a Flask endpoint that accepts POST requests at the '/ask' route.
The request should contain a JSON payload with a 'question' field. Extract the question from the JSON payload.
Call a function named ask_llm (located in a file named legal.py) with the extracted question as an argument.
Return the result of the ask_llm function as the response with a 200 status code.
If any error occurs during the process, return a 500 status code with the error message.
"""
# Add this block to start the Flask app when running locally
if __name__ == "__main__":
.....
仅当生成的代码良好且基本正确时才接受。如果您不熟悉 Python,请将此有效示例复制并粘贴到 main.py
中已有的代码下方。
👉 请确保您在 Web 应用启动之前粘贴以下代码(如果 name == "main":)
@app.route('/ask', methods=['POST'])
def ask_question():
data = request.get_json()
question = data.get('question')
try:
# call the ask_llm in legal.py
answer_markdown = legal.ask_llm(question)
print(f"answer_markdown: {answer_markdown}")
# Return the Markdown as the response
return answer_markdown, 200
except Exception as e:
return f"Error: {str(e)}", 500 # Handle errors appropriately
按照这些步骤操作后,您应该能够成功启用 Gemini Code Assist、设置项目,并使用它在 main.py
文件中生成 ask
函数。
5. 在 Cloud Editor 中进行本地测试
👉 在编辑器的终端中,安装依赖库并在本地启动 Web 界面。
cd ~/legal-eagle/webapp
python -m venv env
source env/bin/activate
export PROJECT_ID=$(gcloud config get project)
pip install -r requirements.txt
python main.py
在 Cloud Shell 终端输出中查找启动消息。Flask 通常会打印消息,指明它正在运行以及运行在哪个端口上。
- Running on http://127.0.0.1:8080
应用需要保持运行状态才能处理请求。
👉 从“网页预览”菜单中选择在端口 8080 上预览。Cloud Shell 会打开一个新的浏览器标签页或窗口,其中包含应用的 Web 预览。
👉 在应用界面中,输入几个与法律诉讼参考资料具体相关的问题,看看 LLM 如何回答。例如,您可以尝试:
- Michael Brown 被判处了多少年监禁?
- Jane Smith 的行为导致了多少未经授权的费用?
- 邻居的证词在 Emily White 案件的调查中发挥了什么作用?
👉 可选:西班牙语版本
- ¿A cuántos años de prisión fue sentenciado Michael Brown?
- ¿Cuánto dinero en cargos no autorizados se generó como resultado de las acciones de Jane Smith?
- ¿Qué papel jugaron los testimonios de los vecinos en la investigación del caso de Emily White?
如果您仔细查看回答,可能会发现模型可能会产生幻觉、回答含糊不清或过于笼统,有时还会误解您的问题,尤其是在它尚未获得特定法律文件访问权限的情况下。
👉 请按 Ctrl+C 停止脚本。
👉 退出虚拟环境,在终端中运行:
deactivate
6. 设置向量存储区
是时候结束 LLM 对法律的这些“创造性解读”了。检索增强生成 (RAG) 可以帮我们解决这个问题!您可以将其视为在 LLM 回答您的问题之前,让其访问功能强大的法律知识库。RAG 不仅依赖于其泛化知识(这些知识可能会模糊不清或过时,具体取决于模型),还会先从可信来源(在本例中为法律文件)中提取相关信息,然后使用该上下文生成更明智、更准确的回答。这就像 LLM 在进入法庭之前先做功课!
为了构建 RAG 系统,我们需要一个位置来存储所有这些法律文件,更重要的是,让这些文件能够按含义进行搜索。这时,Firestore 就派上用场了!Firestore 是 Google Cloud 灵活且可扩缩的 NoSQL 文档数据库。
我们将使用 Firestore 作为向量存储区。我们将法律文件的各个部分存储在 Firestore 中,并为每个部分存储其嵌入内容,即其含义的数值表示形式。
然后,当您向 Legal Eagle 提问时,我们会使用 Firestore 的向量搜索功能来查找与您的查询最相关的法律文本块。检索到的上下文就是 RAG 用来为您提供基于实际法律信息(而不仅仅是 LLM 想象)的答案的依据!
👉 在新标签页/窗口中,前往 Google Cloud 控制台中的 Firestore。
👉 点击创建数据库
👉 选择 Native mode
,并将数据库名称设为 (default)
。
👉 选择单个 region
:us-central1
,然后点击创建数据库。Firestore 将预配您的数据库,这可能需要几分钟时间。
👉 返回 Cloud IDE 的终端 - 在 embedding_vector 字段上创建向量索引,以在 legal_documents 集合中启用向量搜索。
export PROJECT_ID=$(gcloud config get project)
gcloud firestore indexes composite create \
--collection-group=legal_documents \
--query-scope=COLLECTION \
--field-config field-path=embedding,vector-config='{"dimension":"768", "flat": "{}"}' \
--project=${PROJECT_ID}
Firestore 将开始创建向量索引。创建索引可能需要一些时间,尤其是对于较大的数据集。您会看到索引处于“正在创建”状态,构建完成后,该状态会变为“就绪”。
7. 将数据加载到向量存储区
现在,我们已经了解了 RAG 和向量存储区,接下来可以构建用于填充法律库的引擎了!那么,如何才能让法律文件“按含义搜索”呢?神奇之处在于嵌入!您可以将嵌入视为将字词、句子甚至整个文档转换为数值向量(即捕捉其语义含义的数字列表)。相似的概念会获得在向量空间中彼此“接近”的向量。我们会使用强大的模型(例如 Vertex AI 中的模型)来执行此转换。
为了自动加载文档,我们将使用 Cloud Run functions 和 Eventarc。Cloud Run Functions 是一种轻量级无服务器容器,仅在需要时运行代码。我们将把文档处理 Python 脚本打包到容器中,并将其部署为 Cloud Run 函数。
👉 在新标签页/窗口中,前往 Cloud Storage。
👉 点击左侧菜单中的“分桶”。
👉 点击顶部的“+ 创建”按钮。
👉 配置存储分区(重要设置):
- 存储分区名称:yourprojectID-doc-bucket(末尾必须带有 -doc-bucket 后缀)
- 地区:选择
us-central1
地区。 - 存储类别:“标准”。Standard 适合频繁访问的数据。
- 访问权限控制:保留默认选择的“统一访问权限控制”。这样可提供一致的存储分区级访问权限控制。
- 高级选项:在本教程中,默认设置通常足以满足要求。
👉 点击创建按钮以创建存储分区。
👉 您可能会看到有关禁止公开访问的弹出式窗口。保持选中相应复选框,然后点击“确认”。
您现在会在“存储分区”列表中看到新创建的存储分区。请记住您的存储分区名称,稍后会用到。
8. 设置 Cloud Run 函数
👉 在 Cloud Shell 代码编辑器中,前往工作目录 legal-eagle:在 Cloud 编辑器终端中使用 cd 命令创建该文件夹。
cd ~/legal-eagle
mkdir loader
cd loader
👉 创建 main.py
、requirements.txt
和 Dockerfile
文件。在 Cloud Shell 终端中,使用 touch 命令创建文件:
touch main.py requirements.txt Dockerfile
您会看到名为 *loader
的新创建的文件夹和这三个文件。
👉 修改 loader
文件夹下的 main.py
。在左侧的文件资源管理器中,前往您创建文件的目录,然后双击 main.py
以在编辑器中打开该文件。
将以下 Python 代码粘贴到 main.py
中:
此应用会处理上传到 GCS 存储分区的新文件,将文本拆分为多个块,为每个块生成嵌入内容,并将这些块及其嵌入内容存储在 Firestore 中。
import os
import json
from google.cloud import storage
import functions_framework
from langchain_google_vertexai import VertexAI, VertexAIEmbeddings
from langchain_google_firestore import FirestoreVectorStore
from langchain.text_splitter import RecursiveCharacterTextSplitter
import vertexai
PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT") # Get project ID from env
embedding_model = VertexAIEmbeddings(
model_name="text-embedding-004" ,
project=PROJECT_ID,)
COLLECTION_NAME = "legal_documents"
# Create a vector store
vector_store = FirestoreVectorStore(
collection="legal_documents",
embedding_service=embedding_model,
content_field="original_text",
embedding_field="embedding",
)
@functions_framework.cloud_event
def process_file(cloud_event):
print(f"CloudEvent received: {cloud_event.data}") # Print the parsed event data
"""Triggered by a Cloud Storage event.
Args:
cloud_event (functions_framework.CloudEvent): The CloudEvent
containing the Cloud Storage event data.
"""
try:
event_data = cloud_event.data
bucket_name = event_data['bucket']
file_name = event_data['name']
except (json.JSONDecodeError, AttributeError, KeyError) as e: # Catch JSON errors
print(f"Error decoding CloudEvent data: {e} - Data: {cloud_event.data}")
return "Error processing event", 500 # Return an error response
print(f"New file detected in bucket: {bucket_name}, file: {file_name}")
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(file_name)
try:
# Download the file content as string (assuming UTF-8 encoded text file)
file_content_string = blob.download_as_string().decode("utf-8")
print(f"File content downloaded. Processing...")
# Split text into chunks using RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=100,
length_function=len,
)
text_chunks = text_splitter.split_text(file_content_string)
print(f"Text split into {len(text_chunks)} chunks.")
# Add the docs to the vector store
vector_store.add_texts(text_chunks)
print(f"File processing and Firestore upsert complete for file: {file_name}")
return "File processed successfully", 200 # Return success response
except Exception as e:
print(f"Error processing file {file_name}: {e}")
修改 requirements.txt
。将以下代码行粘贴到文件中:
Flask==2.3.3
requests==2.31.0
google-generativeai>=0.2.0
langchain
langchain_google_vertexai
langchain-community
langchain-google-firestore
google-cloud-storage
functions-framework
9. 测试和构建 Cloud Run 函数
👉 我们将在虚拟环境中运行此命令,并为 Cloud Run 函数安装必要的 Python 库。
cd ~/legal-eagle/loader
python -m venv env
source env/bin/activate
pip install -r requirements.txt
👉 启动 Cloud Run functions 函数的本地模拟器
functions-framework --target process_file --signature-type=cloudevent --source main.py
👉 让上一个终端保持运行状态,打开一个新终端,然后运行命令以将文件上传到存储分区。
export DOC_BUCKET_NAME=$(gcloud storage buckets list --format="value(name)" | grep doc-bucket)
gsutil cp ~/legal-eagle/court_cases/case-01.txt gs://$DOC_BUCKET_NAME/
👉 在模拟器运行时,您可以向其发送测试 CloudEvent。您需要在 IDE 中使用单独的终端来执行此操作。
curl -X POST -H "Content-Type: application/json" \
-d "{
\"specversion\": \"1.0\",
\"type\": \"google.cloud.storage.object.v1.finalized\",
\"source\": \"//storage.googleapis.com/$DOC_BUCKET_NAME\",
\"subject\": \"objects/case-01.txt\",
\"id\": \"my-event-id\",
\"time\": \"2024-01-01T12:00:00Z\",
\"data\": {
\"bucket\": \"$DOC_BUCKET_NAME\",
\"name\": \"case-01.txt\"
}
}" http://localhost:8080/
它应该返回“确定”。
👉 您将验证 Firestore 中的数据,前往 Google Cloud 控制台,依次前往“数据库”和“Firestore”,然后选择“数据”标签页和 legal_documents
集合。您会看到集合中已创建新文档,每个文档都代表上传文件中的一段文本。
👉 在运行模拟器的终端中,输入 Ctrl+C
以退出。然后关闭第二个终端。
👉 运行 deactivate 以退出虚拟环境。
deactivate
10. 构建容器映像并推送到制品代码库
👉 现在可以将此功能部署到云端了。在文件资源管理器中,双击 Dockerfile。让 Gemini 为您生成 Dockerfile,打开 Gemini Code Assist,然后使用以下提示生成文件。
In the loader folder,
Generate a Dockerfile for a Python 3.12 Cloud Run service that uses functions-framework. It needs to:
1. Use a Python 3.12 slim base image.
2. Set the working directory to /app.
3. Copy requirements.txt and install Python dependencies.
4. Copy main.py.
5. Set the command to run functions-framework, targeting the 'process_file' function on port 8080
按照最佳实践,建议点击与打开的文件进行差异比较(两个方向相反的箭头,并接受更改)。
👉 如果您是容器新手,可以参考以下有效示例:
# Use a Python 3.12 slim base image
FROM python:3.12-slim
# Set the working directory to /app
WORKDIR /app
# Copy requirements.txt and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy main.py
COPY main.py .
# Set the command to run functions-framework
CMD ["functions-framework", "--target", "process_file", "--port", "8080"]
👉 在终端中,创建一个制品库来存储我们将要构建的 Docker 映像。
gcloud artifacts repositories create my-repository \
--repository-format=docker \
--location=us-central1 \
--description="My repository"
您应该会看到 Created repository [my-repository].。
👉 运行以下命令以构建 Docker 映像。
cd ~/legal-eagle/loader
export PROJECT_ID=$(gcloud config get project)
docker build -t gcr.io/${PROJECT_ID}/legal-eagle-loader .
👉 您现在需要将该映像推送到注册表中
export PROJECT_ID=$(gcloud config get project)
docker tag gcr.io/${PROJECT_ID}/legal-eagle-loader us-central1-docker.pkg.dev/${PROJECT_ID}/my-repository/legal-eagle-loader
docker push us-central1-docker.pkg.dev/${PROJECT_ID}/my-repository/legal-eagle-loader
Docker 映像现在已在 my-repository 制品库中提供。
11. 创建 Cloud Run 函数并设置 Eventarc 触发器
在深入了解法律文件加载器的部署细节之前,我们先简要了解一下所涉及的组件:Cloud Run 是一种全代管式无服务器平台,可让您快速轻松地部署容器化应用。它会剥离基础架构管理工作,让您专注于编写和部署代码。
我们将把文档加载器部署为 Cloud Run 服务。现在,我们继续设置 Cloud Run 函数:
👉 在 Google Cloud 控制台中,前往 Cloud Run。
👉 前往部署容器,然后在下拉菜单中点击服务。
👉 配置 Cloud Run 服务:
- 容器映像:点击网址字段中的“选择”。找到您推送到 Artifact Registry 的映像网址(例如 us-central1-docker.pkg.dev/your-project-id/my-repository/legal-eagle-loader/yourimage)。
- 服务名称:
legal-eagle-loader
- 区域:选择
us-central1
区域。 - 身份验证:在本讲座中,您可以选择“允许未通过身份验证的调用”。对于生产环境,您可能需要限制访问权限。
- 容器、网络、安全性:默认。
👉 点击创建。Cloud Run 将部署您的服务。
为了在向存储分区添加新文件时自动触发此服务,我们将使用 Eventarc。借助 Eventarc,您可以将来自各种来源的事件路由到您的服务,从而创建事件驱动型架构。
通过设置 Eventarc,我们的 Cloud Run 服务会在新添加的文档上传后立即自动将其加载到 Firestore 中,从而为 RAG 应用实现实时数据更新。
👉 在 Google Cloud 控制台中,前往 EventArc 下的触发器。点击“+ 创建触发器”。👉 配置 Eventarc 触发器:
- 触发器名称:
legal-eagle-upload-trigger
。 - TriggerType:Google 来源
- 事件提供方:选择 Cloud Storage。
- 活动类型:选择
google.cloud.storage.object.v1.finalized
- Cloud Storage 存储分区:从下拉菜单中选择您的 GCS 存储分区。
- 目标类型:“Cloud Run 服务”。
- 服务:选择
legal-eagle-loader
。 - 区域:
us-central1
- 路径:暂时将此项留空。
- 授予页面上提示的所有权限
👉 点击创建。Eventarc 现在将设置触发器。
Cloud Run 服务需要获得从各种组件读取文件的权限。我们需要向服务账号授予所需的权限。
12. 将法律文件上传到 GCS 存储分区
👉 将法院诉讼案文件上传到您的 GCS 存储分区。请记得替换为您的存储分区名称。
export DOC_BUCKET_NAME=$(gcloud storage buckets list --format="value(name)" | grep doc-bucket)
gsutil cp ~/legal-eagle/court_cases/case-02.txt gs://$DOC_BUCKET_NAME/
gsutil cp ~/legal-eagle/court_cases/case-03.txt gs://$DOC_BUCKET_NAME/
gsutil cp ~/legal-eagle/court_cases/case-06.txt gs://$DOC_BUCKET_NAME/
如需监控 Cloud Run 服务日志,请依次前往 Cloud Run -> 您的服务 legal-eagle-loader
->“日志”。检查日志中是否包含成功处理消息,包括:
xxx
POST200130 B8.3 sAPIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html) https://legal-eagle-loader-bmngrueyta-uc.a.run.app/?__GCP_CloudEventsMode=GCS_NOTIFICATION
xxx
POST200130 B520 msAPIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html) https://legal-eagle-loader-bmngrueyta-uc.a.run.app/?__GCP_CloudEventsMode=GCS_NOTIFICATION
xxx
POST200130 B514 msAPIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html) https://legal-eagle-loader-bmngrueyta-uc.a.run.app/?__GCP_CloudEventsMode=GCS_NOTIFICATION
根据日志记录的设置速度,您还可以在此处看到更详细的日志
"CloudEvent received:"
"New file detected in bucket:"
"File content downloaded. Processing..."
"Text split into ... chunks."
"File processing and Firestore upsert complete..."
在日志中查找任何错误消息,并在必要时进行问题排查。
👉 验证 Firestore 中的数据。然后打开 legal_documents 集合。
👉 您应该会在集合中看到新创建的文档。每个文档都将代表您上传的文件中的一段文本,并且将包含:
metadata: currently empty
original_text_chunk: The text chunk content.
embedding_: A list of floating-point numbers (the Vertex AI embedding).
13. 实现 RAG
LangChain 是一个功能强大的框架,旨在简化由大语言模型 (LLM) 提供支持的应用的开发流程。LangChain 提供了一个高级别抽象层,让您无需直接处理 LLM API、提示工程和数据处理的复杂性。它提供预构建的组件和工具,用于执行各种任务,例如连接到各种 LLM(如 OpenAI、Google 或其他公司的 LLM)、构建复杂的操作链(例如,先检索数据,然后进行总结)以及管理对话记忆。
对于 RAG 而言,LangChain 中的向量存储区对于实现 RAG 的检索方面至关重要。它们是专门的数据库,旨在高效存储和查询向量嵌入,其中语义相似的文本片段会映射到向量空间中彼此接近的点。LangChain 负责处理底层管道,让开发者能够专注于 RAG 应用的核心逻辑和功能。这可显著缩短开发时间并降低复杂性,让您能够快速设计原型并部署基于 RAG 的应用,同时充分利用 Google Cloud 基础架构的稳健性和可伸缩性。
了解 LangChain 后,您现在需要更新 webapp
文件夹下的 legal.py
文件,以实现 RAG。这样一来,LLM 便能够在提供回答之前在 Firestore 中搜索相关文档。
👉 从 langchain 和 vertexai 导入 FirestoreVectorStore
和其他必需的模块。将以下内容添加到当前 legal.py
from langchain_google_vertexai import VertexAIEmbeddings
from langchain_google_firestore import FirestoreVectorStore
👉 初始化 Vertex AI 和嵌入模型。您将使用 text-embedding-004
。在导入模块后立即添加以下代码。
PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT") # Get project ID from env
embedding_model = VertexAIEmbeddings(
model_name="text-embedding-004" ,
project=PROJECT_ID,)
👉 创建指向 legal_documents 集合的 FirestoreVectorStore,使用已初始化的嵌入模型并指定内容和嵌入字段。将此代码添加到之前的嵌入模型代码之后。
COLLECTION_NAME = "legal_documents"
# Create a vector store
vector_store = FirestoreVectorStore(
collection="legal_documents",
embedding_service=embedding_model,
content_field="original_text",
embedding_field="embedding",
)
👉 定义一个名为 search_resource
的函数,该函数接受查询,使用 vector_store.similarity_search 执行相似度搜索,并返回合并后的结果。
def search_resource(query):
results = []
results = vector_store.similarity_search(query, k=5)
combined_results = "\n".join([result.page_content for result in results])
print(f"==>{combined_results}")
return combined_results
👉 替换 ask_llm
函数,并使用 search_resource
函数根据用户查询检索相关上下文。
def ask_llm(query):
try:
query_message = {
"type": "text",
"text": query,
}
relevant_resource = search_resource(query)
input_msg = HumanMessage(content=[query_message])
prompt_template = ChatPromptTemplate.from_messages(
[
SystemMessage(
content=(
"You are a helpful assistant, and you are with the attorney in a courtroom, you are helping him to win the case by providing the information he needs "
"Don't answer if you don't know the answer, just say sorry in a funny way possible"
"Use high engergy tone, don't use more than 100 words to answer"
f"Here is some context that is relevant to the question {relevant_resource} that you might use"
)
),
input_msg,
]
)
prompt = prompt_template.format()
response = llm.invoke(prompt)
print(f"response: {response}")
return response
except Exception as e:
print(f"Error sending message to chatbot: {e}") # Log this error too!
return f"Unable to process your request at this time. Due to the following reason: {str(e)}"
👉 可选:西班牙语版本
Sustituye el siguiente texto como se indica: You are a helpful assistant,
to You are a helpful assistant that speaks Spanish,
👉 在 legal.py 中实现 RAG 后,您应在部署之前在本地对其进行测试,使用以下命令运行应用:
cd ~/legal-eagle/webapp
source env/bin/activate
python main.py
👉 使用 webpreview 访问应用,与助理对话,然后输入 ctrl+c
退出本地运行的进程。运行 deactivate 退出虚拟环境。
deactivate
👉 将 Web 应用部署到 Cloud Run 的方式与加载器函数类似。您将构建 Docker 映像、为其添加标记并将其推送到 Artifact Registry:
export PROJECT_ID=$(gcloud config get project)
docker build -t gcr.io/${PROJECT_ID}/legal-eagle-webapp .
docker tag gcr.io/${PROJECT_ID}/legal-eagle-webapp us-central1-docker.pkg.dev/${PROJECT_ID}/my-repository/legal-eagle-webapp
docker push us-central1-docker.pkg.dev/${PROJECT_ID}/my-repository/legal-eagle-webapp
👉 现在,您可以将 Web 应用部署到 Google Cloud 了。在终端中,运行以下命令:
export PROJECT_ID=$(gcloud config get project)
gcloud run deploy legal-eagle-webapp \
--image us-central1-docker.pkg.dev/$PROJECT_ID/my-repository/legal-eagle-webapp \
--region us-central1 \
--set-env-vars=GOOGLE_CLOUD_PROJECT=${PROJECT_ID} \
--allow-unauthenticated
在 Google Cloud 控制台中前往 Cloud Run,验证部署。您应该会看到列出了一个名为 legal-eagle-webapp
的新服务。
点击服务进入其详情页面,您可以在顶部找到已部署的网址。
👉 现在,在新浏览器标签页中打开已部署的网址。您可以与法律助理互动,并询问与您已加载的诉讼案(位于 court_cases 文件夹下)相关的问题:
- Michael Brown 被判处了多少年监禁?
- Jane Smith 的行为导致了多少未经授权的费用?
- 邻居的证词在 Emily White 案件的调查中发挥了什么作用?
👉 可选:西班牙语版本
- ¿A cuántos años de prisión fue sentenciado Michael Brown?
- ¿Cuánto dinero en cargos no autorizados se generó como resultado de las acciones de Jane Smith?
- ¿Qué papel jugaron los testimonios de los vecinos en la investigación del caso de Emily White?
您应该会注意到,回答现在更加准确,并且基于您上传的法律文件的内容,这充分展示了 RAG 的强大功能!
恭喜您完成本工作坊!您已成功使用 LLM、LangChain 和 Google Cloud 构建并部署了法律文件分析应用。您已了解如何提取和处理法律文件,如何使用 RAG 通过相关信息增强 LLM 回答,以及如何将应用部署为无服务器服务。通过这些知识和构建的应用,您可以进一步探索 LLM 在法律任务方面的强大功能。做得好!”
14. 挑战
多种媒体类型::
如何提取和处理各种媒体类型(例如庭审视频和录音),并提取相关文本。
在线素材资源:
如何实时处理网页等在线资源。