使用LlamaIndex和Flask构建具有自定义数据源的聊天机器人。
嗨,在这个博客中,我们将使用llama索引和Flask来创建一个聊天机器人。
什么是Llama指数-
Llama Index是一款前沿的聊天机器人开发平台,能够赋予开发人员创建自定义聊天机器人的能力,无需过多的编程知识。凭借其用户友好界面和强大的功能集,Llama Index使聊天机器人的开发对初学者和有经验的开发人员都变得易于理解。
Llama指数通过检索增强生成(RAG)为您的模型提供自定义数据源,保持HTML结构不变。
检索增强生成(RAG)
LLMs在处理海量数据时经过训练,但它们并没有经过您的数据训练。检索增强生成(RAG)通过将您的数据添加到LLMs已经能够访问的数据中来解决这个问题。
在本文中,我们将向您展示如何使用LlamaIndex和Flask在四个简单步骤中构建聊天机器人来增强GPT-3.5的功能。
- 配置应用程序秘密
- 安装依赖库
- 构建应用程序
- 部署应用程序!
1- 配置应用程序的秘密:
在这个应用程序中,我们使用了GPT-3.5 turbo,所以您还需要一个Open AI API密钥。按照我们的指示获取我们自己的Open AI API密钥。
1- 前往https://platform.openai.com/account/api-keys。 2- 点击“+ 创建新的秘密密钥”按钮。 3- 输入一个标识名称(可选),然后点击“创建秘密密钥”按钮。 4- 复制在本教程中将要使用的API密钥。
2- 安装依赖库:
如果您正在使用本地计算机工作,请使用pip安装依赖。
pip install flask openai llama-index nltk pypdf
如果您计划在云上部署此应用程序,并且需要创建一个包含以下内容的requirements.txt文件:
flask
openai
llama-index
nltk
pypdf
3- 构建应用程序:
首先,我们导入此应用程序中使用的所有库。
from flask import Flask, render_template, request
from llama_index import VectorStoreIndex, ServiceContext, Document
from llama_index.llms import OpenAI
from llama_index import SimpleDirectoryReader
import openai
import pypdf
import os
SimpleDirectoryReader:从指定的目录(“upload”)读取数据。ServiceContext:为OpenAI模型配置设置和参数。VectorStoreIndex:从加载的文档创建索引。chat_engine:使用指定的聊天模式(“condense_question”)和详细程度创建聊天引擎。
# open.api_key = "enter your api key directly or import dotenv file !"
openai.api_key = "XXXXXXXXXXXXXXXXXXXXXX"
# created a function to read data from our direcetry
def read_data():
reader = SimpleDirectoryReader(input_dir="upload", recursive=True)
docs = reader.load_data()
service_context = ServiceContext.from_defaults(llm=OpenAI(model="gpt-3.5-turbo", temperature=0.5, system_prompt="You are an expert on the docs and can provide helpful summaries"))
index = VectorStoreIndex.from_documents(docs, service_context=service_context)
chat_engine = index.as_chat_engine(chat_mode="condense_question", verbose=True)
return chat_engine
在提问之前,请仔细考虑你对Prompt的基本理解,保持HTML的结构。
提示:提示写作(或工程)是创建输入(通常是文本),以指示生成式人工智能生成所需的响应的过程。换句话说,提示是我们要求人工智能做某事的方式。
提示原则:写出清晰具体的指示,并给模型足够的时间来思考
chat_engine = read_data()
prompt ="""Summarize the main points and key information from the provided PDF document.
The document covers [brief description of the content]. Please generate a concise summary of approximately 3-4 sentences. """
response = chat_engine.chat(prompt)
print(response.response)
回复:
现在我们将使用Flask来创建我们的应用程序。
from flask import Flask, render_template, request
from llama_index import VectorStoreIndex, ServiceContext, Document
from llama_index.llms import OpenAI
from llama_index import SimpleDirectoryReader
import openai
import pypdf
import os
openai.api_key = 'import or insert your open ai api key here'
def read_data():
reader = SimpleDirectoryReader(input_dir="upload", recursive=True)
docs = reader.load_data()
service_context = ServiceContext.from_defaults(llm=OpenAI(model="gpt-3.5-turbo", temperature=0.5, system_prompt="You are an expert on the docs and can provide helpful summaries"))
index = VectorStoreIndex.from_documents(docs, service_context=service_context)
chat_engine = index.as_chat_engine(chat_mode="condense_question", verbose=True)
return chat_engine
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/upload', methods=['POST'])
def upload():
if 'pdf_file' in request.files:
pdf_file = request.files['pdf_file']
if pdf_file.filename.endswith('.pdf'):
upload_folder = 'upload'
os.makedirs(upload_folder, exist_ok=True)
pdf_path = os.path.join(upload_folder, pdf_file.filename)
pdf_file.save(pdf_path)
print(f"Uploaded PDF path: {pdf_path}")
return render_template('chat.html', upload_success=True)
else:
return render_template('index.html', upload_error="Invalid file format. Please upload a PDF.")
else:
return render_template('index.html', upload_error="No file uploaded.")
@app.route('/chat', methods=['POST'])
def chat():
chat_engine = read_data()
if request.method == 'POST':
prompt = request.form['prompt']
response = chat_engine.chat(prompt)
return render_template('chat.html', prompt=prompt, response=response.response)
if __name__ == '__main__':
app.run(debug=True)
Html文件在这里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 Uploader</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 120vh;
}
.container {
max-width: 400px;
background-color: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
text-align: center;
color: #333333;
}
form {
display: flex;
flex-direction: column;
}
input {
margin-bottom: 10px;
padding: 8px;
font-size: 14px;
}
button {
background-color: #3498db;
color: #ffffff;
padding: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.error {
color: #e74c3c;
margin-top: 10px;
}
.success {
color: #27ae60;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>Document Uploader</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="pdf_file" accept=".pdf" required>
<button type="submit">Upload Document</button>
</form>
{% if upload_error %}
<p class="error">{{ upload_error }}</p>
{% endif %}
{% if upload_success %}
<p class="success">Document uploaded successfully!</p>
{% endif %}
</div>
</body>
</html>
聊天.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=UTF-8 <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat With Document</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f7f7f7;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
form {
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 20px;
text-align: center;
}
label {
font-size: 16px;
margin-bottom: 10px;
display: block;
}
input {
width: 100%;
padding: 10px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
margin-bottom: 20px;
}
button {
background-color: #3498db;
color: #ffffff;
padding: 12px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.response-container {
text-align: center;
margin-top: 30px;
}
h2 {
color: #333333;
}
p {
font-size: 18px;
color: #555555;
}
</style>
</head>
<body>
<form method="post" action="{{ url_for('chat') }}">
<label for="prompt">Ask me anything about your document:</label>
<br>
<input type="text" id="prompt" name="prompt" required>
<br>
<button type="submit">Chat</button>
</form>
{% if prompt %}
<div class="response-container">
<h2>Your Question:</h2>
<p>{{ prompt }}</p>
<h2>Response:</h2>
<p>{{ response }}</p>
</div>
{% endif %}
</body>
</html>
这是一个非常简单的用户界面,请根据您的要求进行更改。
谢谢你