AWS平台上建立一个生成式人工智能专业文文档问答式网站,前端用Flask框架,后端用Fast API,前端调用后端的唯一API来完成大模型文档搜索的功能,使用AWS Bedrock里的Titan和Llama3模型,以及OpenAI 4.0 API来调用模型并提供内部的配置参数以供选择,向量数据库用langchain和faiss库,在Sagemaker中访问S3里PDF文件逐页导入内容,生成单独向量数据库文件搜索文档,以及用Amazon Kendra文档智能搜索服务实现搜索文档,作为另一种实现,通过配置参数来选择,最后将前端和后端用Docker打包镜像文件,上传到AWS ECS中运行。请详细地设计这样的一种应用程序的实现和部署方式,并给出关键部分的Python代码实现。
这是一个相对复杂的任务,涉及多个AWS服务、AI模型、以及前后端技术的集成。我们可以将其拆分成几个模块,逐步实现。
1. 系统架构设计
首先,我们设计一个清晰的架构:
- 前端: 使用 Flask 创建一个简单的Web应用,提供用户交互界面,让用户上传PDF文档并输入查询内容。
- 后端: 使用 FastAPI 提供API接口,处理来自前端的请求,调用各种AI模型进行推理,或者查询本地的向量数据库(FAISS)/Kendra服务。
- 文档存储: 使用 S3 存储PDF文件,SageMaker 中的模型和服务来提取文档内容并生成向量。
- 模型选择: 提供Titan和Llama3模型在AWS Bedrock中进行选择,或者调用OpenAI 4.0的API。提供一个接口让前端选择并切换模型。
- 向量存储与搜索: 使用 FAISS 和 LangChain 来存储和查询文档的向量,另外通过 Kendra 提供文档智能搜索功能作为备选。
- 容器化与部署: 使用 Docker 打包应用并将其部署到 AWS ECS 中,保证服务的可伸缩性和高可用性。
2. 前端部分:Flask应用
Flask应用将负责向用户展示上传文件和查询输入的页面。用户输入的查询请求将通过AJAX传递给后端API。
python
# app.py - Flask Frontend Application
from flask import Flask, render_template, request, jsonify
import requests
app = Flask(__name__)
# FastAPI backend URL
BACKEND_URL = "http://<backend-service-url>/api/query"
@app.route('/')
def index():
return render_template('index.html')
@app.route('/submit_query', methods=['POST'])
def submit_query():
query = request.form['query']
selected_model = request.form['model']
response = requests.post(BACKEND_URL, json={'query': query, 'model': selected_model})
data = response.json()
return jsonify(data)
if __name__ == '__main__':
app.run(debug=True)
Flask应用提供了一个简单的HTML表单,用户输入查询并选择模型后,将请求发送到FastAPI后端进行处理。
html
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document Search</title>
</head>
<body>
<h1>Document Query Interface</h1>
<form id="queryForm">
<label for="query">Query:</label>
<input type="text" id="query" name="query" required>
<label for="model">Choose a Model:</label>
<select id="model" name="model">
<option value="Titan">Titan</option>
<option value="Llama3">Llama3</option>
<option value="OpenAI">OpenAI 4.0</option>
</select>
<button type="submit">Submit</button>
</form>
<div id="result">
<h2>Search Results:</h2>
<pre id="response"></pre>
</div>
<script>
document.getElementById('queryForm').onsubmit = async function(event) {
event.preventDefault();
const query = document.getElementById('query').value;
const model = document.getElementById('model').value;
const response = await fetch('/submit_query', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({query, model}),
});
const result = await response.json();
document.getElementById('response').textContent = JSON.stringify(result, null, 2);
};
</script>
</body>
</html>
3. 后端部分:FastAPI应用
FastAPI应用将负责接收前端的请求,调用AWS服务(如AWS Bedrock,OpenAI,FAISS,或Kendra),并返回查询结果。
python
# main.py - FastAPI Backend Application
from fastapi import FastAPI, Query
from pydantic import BaseModel
import openai
import boto3
import os
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA
# AWS Configurations
BEDROCK_CLIENT = boto3.client('bedrock', region_name='us-west-2')
S3_CLIENT = boto3.client('s3')
# OpenAI API Key
openai.api_key = os.getenv("OPENAI_API_KEY")
# Define a model selection object
class QueryRequest(BaseModel):
query: str
model: str
app = FastAPI()
@app.post("/api/query")
async def query(request: QueryRequest):
query = request.query
model = request.model
if model == "OpenAI":
response = openai.Completion.create(
model="gpt-4",
prompt=query,
max_tokens=150
)
return {"response": response['choices'][0]['text']}
elif model == "Titan":
response = BEDROCK_CLIENT.invoke_model(
ModelId="titan-1",
Body=query
)
return {"response": response['Body'].read().decode()}
elif model == "Llama3":
# Assuming use of Llama3 in a similar fashion to Titan
response = BEDROCK_CLIENT.invoke_model(
ModelId="llama3-1",
Body=query
)
return {"response": response['Body'].read().decode()}
else:
return {"error": "Model not supported."}
@app.post("/api/upload_document")
async def upload_document(file: bytes):
# Save to S3
s3_response = S3_CLIENT.put_object(Bucket="my-bucket", Key="document.pdf", Body=file)
return {"status": "success", "s3_key": s3_response["Key"]}
@app.get("/api/search_vector")
async def search_vector(query: str):
# Load the FAISS index
vector_store = FAISS.load_local("faiss_index")
retriever = vector_store.as_retriever()
# Perform vector search
result = retriever.get_relevant_documents(query)
return {"results": result}
4. FAISS 和 LangChain 集成
对于文档的向量化,我们使用 LangChain 和 FAISS。首先,从S3获取PDF文件,使用SageMaker进行内容提取,然后将提取的文本进行嵌入向量化,最后存储到FAISS数据库中。
python
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.document_loaders import PyPDFLoader
from langchain.chains import RetrievalQA
import boto3
# S3获取PDF文件
def load_pdf_from_s3(bucket, key):
s3 = boto3.client('s3')
obj = s3.get_object(Bucket=bucket, Key=key)
return obj['Body'].read()
# 文档向量化
def process_pdf_to_faiss(pdf_file):
loader = PyPDFLoader(pdf_file)
pages = loader.load_and_split()
# Create embeddings
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(pages, embeddings)
# Save FAISS index
vectorstore.save_local("faiss_index")
5. AWS Sagemaker与PDF处理
使用 SageMaker 进行PDF文本提取。可以使用 Boto3
和 SageMaker
SDK 来调用预训练模型(如Tesseract OCR)。
python
import boto3
def process_pdf_with_sagemaker(pdf_file_path):
sagemaker_client = boto3.client('sagemaker-runtime')
with open(pdf_file_path, 'rb') as f:
payload = f.read()
response = sagemaker_client.invoke_endpoint(
EndpointName='your-endpoint-name',
Body=payload,
ContentType='application/pdf',
Accept='application/json'
)
return response['Body'].read().decode()
6. 部署与容器化
使用 Docker 创建容器镜像,并将其上传到 ECR ,然后通过 ECS 部署。
Dockerfile
# Dockerfile
FROM python:3.10-slim
WORKDIR /app
# 安装必要的依赖
COPY requirements.txt .
RUN pip install -r requirements.txt
# 复制项目文件
COPY . .
# 启动 Flask + FastAPI 服务
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
bash
# 构建镜像
docker build -t your-app-name .
# 登录 AWS ECR
aws ecr get-login-password --region your-region | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region
>.amazonaws.com
# 将镜像推送到ECR
docker tag your-app-name:latest <aws_account_id>.dkr.ecr.<region>.amazonaws.com/your-repository:latest
docker push <aws_account_id>.dkr.ecr.<region>.amazonaws.com/your-repository:latest
通过 ECS 设置 Fargate 服务,确保容器自动扩展和管理。
7. 总结
上述设计实现了一个生成式人工智能文档问答系统,整合了多个AWS服务(Bedrock、SageMaker、Kendra等)以及前后端技术。关键组件包括PDF文档的处理和存储、AI模型的调用、向量搜索的实现等。