dede手机医院网站模板下载辽宁省建设注册中心网站
dede手机医院网站模板下载,辽宁省建设注册中心网站,新冠疫苗接种查询,百度运营公司问答系统需求文档
一、项目概述
本项目旨在开发一个能够上传 PDF 文件#xff0c;并基于 PDF 内容进行问答互动的系统。用户可以上传 PDF 文件#xff0c;系统将解析 PDF 内容#xff0c;并允许用户通过对话框进行问答互动#xff0c;获取有关 PDF 文件内容的信息。
二、…问答系统需求文档
一、项目概述
本项目旨在开发一个能够上传 PDF 文件并基于 PDF 内容进行问答互动的系统。用户可以上传 PDF 文件系统将解析 PDF 内容并允许用户通过对话框进行问答互动获取有关 PDF 文件内容的信息。
二、功能需求
2.1 用户上传 PDF
功能描述用户可以通过文件选择框上传一个 PDF 文件。前端需求 提供文件选择框。显示文件上传进度。上传成功后显示文件名和上传成功提示。 后端需求 接收并保存用户上传的 PDF 文件。确保上传的文件格式正确仅支持 PDF。限制文件大小如最大 50 MB。
2.2 PDF 内容解析
功能描述系统解析上传的 PDF 文件内容将其转换为可处理的文本格式。前端需求 显示解析进度。提示用户解析成功或失败。 后端需求 使用 PDF 解析库如 PyMuPDF、pdfminer提取 PDF 文本内容。处理解析错误并返回相应提示。
2.3 用户问答交互
功能描述用户可以在对话框中输入问题系统基于解析的 PDF 内容回答问题。前端需求 提供输入框供用户输入问题。显示用户问题和系统回答。 后端需求 基于解析的 PDF 内容构建问答模型如使用 NLP 模型。处理用户问题并生成答案。返回答案给前端显示。
三、接口设计
5.1 上传 PDF 文件接口
URL/upload方法POST请求参数 file用户上传的 PDF 文件 响应参数 成功{ status: success, message: File uploaded successfully., file_id: unique_file_id }失败{ status: error, message: File upload failed. }
5.2 提取 PDF 内容接口
URL/parse方法POST请求参数 file_id已上传文件的唯一标识符 响应参数 成功{ status: success, message: File parsed successfully., content: parsed_content }失败{ status: error, message: File parsing failed. }
5.3 问答接口
URL/ask方法POST请求参数 file_id已上传文件的唯一标识符question用户输入的问题 响应参数 成功{ status: success, answer: answer_to_question }失败{ status: error, message: Unable to retrieve answer. }
技术实现
系统架构
前端 文件上传界面问答交互界面 后端 文件接收与存储模块PDF 内容解析模块问答处理模块基于 LangChain 数据库 存储上传文件信息和解析内容
技术栈
前端 HTML/CSS/JavaScriptVue.js 后端 编程语言Python框架FlaskPDF 解析库PyMuPDF、pdfminer问答引擎LangChain 数据库 SQLite
前端实现
安装 Vue CLI
npm install -g vue/cli
vue create pdf-qa-frontend
cd pdf-qa-frontend创建组件
在 src/components 目录下创建 FileUpload.vue 和 QuestionAnswer.vue。
FileUpload.vue
templatediv classupload-containerinput typefile changeonFileChange classfile-input accept.pdf,.md/button clickuploadFile classupload-buttonUpload/buttonp v-ifmessage classupload-message{{ message }}/pdiv v-ifuploadProgress 0 classprogress-containerdiv classprogress-bar :style{ width: uploadProgress % }/divp{{ uploadProgress }}%/p/div/div
/templatescript
export default {name: FileUpload,data() {return {file: null,message: ,uploadProgress: 0};},methods: {onFileChange(event) {this.file event.target.files[0];},uploadFile() {if (!this.file) {this.message Please select a file first.;return;}let formData new FormData();formData.append(file, this.file);let xhr new XMLHttpRequest();xhr.open(POST, http://localhost:5000/upload, true);xhr.upload.onprogress (event) {if (event.lengthComputable) {this.uploadProgress Math.round((event.loaded / event.total) * 100);}};xhr.onload () {if (xhr.status 200) {let response JSON.parse(xhr.responseText);this.message response.message;this.uploadProgress 0;} else {this.message Error uploading file.;this.uploadProgress 0;}};xhr.onerror () {this.message Error uploading file.;this.uploadProgress 0;};xhr.send(formData);}}
};
/scriptstyle scoped
.upload-container {display: flex;flex-direction: column;align-items: center;margin-bottom: 20px;
}.file-input {margin-bottom: 10px;
}.upload-button {padding: 8px 16px;background-color: #007bff;color: white;border: none;border-radius: 4px;cursor: pointer;
}.upload-button:hover {background-color: #0056b3;
}.upload-message {margin-top: 10px;color: #28a745;
}.progress-container {width: 100%;max-width: 600px;border: 1px solid #ccc;border-radius: 4px;overflow: hidden;margin-top: 10px;position: relative;
}.progress-bar {height: 20px;background-color: #28a745;transition: width 0.4s ease;
}.progress-container p {position: absolute;width: 100%;text-align: center;margin: 0;line-height: 20px;color: white;font-weight: bold;
}
/style
QuestionAnswer.vue
templatediv classqa-containerdiv classinput-containerinputtypetextv-modelquestionplaceholderAsk a question...keyup.enteraskQuestionclassquestion-input/button clickaskQuestion classask-buttonAsk/button/divdiv classhistory-container v-ifdialogHistory.lengthdiv classdialog v-for(dialog, index) in dialogHistory :keyindexpstrongYou:/strong {{ dialog.question }}/ppstrongBot:/strong {{ dialog.answer }}/p/div/div/div
/templatescript
export default {name: QuestionAnswer,data() {return {question: ,answer: ,dialogHistory: [],fileId: your-file-id // Replace with actual file ID after upload};},methods: {async askQuestion() {if (!this.question) {return;}try {let response await fetch(http://localhost:5000/ask, {method: POST,headers: {Content-Type: application/json},body: JSON.stringify({question: this.question,file_id: this.fileId})});let result await response.json();this.answer result.answer;this.dialogHistory.push({question: this.question,answer: this.answer});this.question ;} catch (error) {console.error(Error asking question:, error);}}}
};
/scriptstyle scoped
.qa-container {display: flex;flex-direction: column;align-items: center;
}.input-container {display: flex;width: 100%;max-width: 600px;margin-bottom: 20px;
}.question-input {flex: 1;padding: 10px;border: 1px solid #ccc;border-radius: 4px 0 0 4px;font-size: 16px;
}.ask-button {padding: 10px 20px;background-color: #28a745;color: white;border: none;border-radius: 0 4px 4px 0;cursor: pointer;
}.ask-button:hover {background-color: #218838;
}.history-container {width: 100%;max-width: 600px;border: 1px solid #ccc;border-radius: 4px;padding: 10px;background-color: #f9f9f9;
}.dialog {margin-bottom: 10px;
}.dialog p {margin: 5px 0;
}
/style
App.vue
templatediv idapp classapp-containerFileUpload /QuestionAnswer //div
/templatescript
import FileUpload from ./components/FileUpload.vue;
import QuestionAnswer from ./components/QuestionAnswer.vue;export default {name: App,components: {FileUpload,QuestionAnswer}
};
/scriptstyle
.app-container {display: flex;flex-direction: column;align-items: center;padding: 20px;
}
/style
后端实现
安装 Flask 及相关依赖
pip install Flask flask-cors PyMuPDF pdfminer.six semantic-kernel创建 Flask 应用
在项目根目录下创建 app.py。确保后端 Flask 代码可以正确处理并解析 MD 文件
import timeimport markdown
from flask import Flask, request, jsonify
from flask_cors import CORS
import fitz # PyMuPDF
import sqlite3import os# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv_ load_dotenv(find_dotenv())
OPENAI_API_KEY os.getenv(OPENAI_API_KEY)from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain_community.document_loaders import PyPDFLoaderapp Flask(__name__)
CORS(app)
UPLOAD_FOLDER uploads/
os.makedirs(UPLOAD_FOLDER, exist_okTrue)
app.config[UPLOAD_FOLDER] UPLOAD_FOLDERapp.route(/upload, methods[POST])
def upload_file():if file not in request.files:return jsonify({status: error, message: No file part})file request.files[file]if file.filename :return jsonify({status: error, message: No selected file})if file:filename file.filenamefile_id filename # In a real app, use a unique identifierfile_path os.path.join(app.config[UPLOAD_FOLDER], filename)file.save(file_path)if filename.endswith(.pdf):content parse_pdf(file_path)elif filename.endswith(.md):content parse_md(file_path)else:return jsonify({status: error, message: Unsupported file type})save_file_to_db(file_id, filename, content)return jsonify({status: success, message: File uploaded and parsed successfully, file_id: file_id})def parse_pdf(file_path):doc fitz.open(file_path)text for page_num in range(len(doc)):page doc.load_page(page_num)text page.get_text()return textdef parse_md(file_path):with open(file_path, r, encodingutf-8) as file:text file.read()return markdown.markdown(text)# Prompt模板
template Answer the question based only on the following context:
{context}Question: {question}
prompt ChatPromptTemplate.from_template(template)# 模型
model ChatOpenAI(modelgpt-4-turbo, temperature0)from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthroughrag_chain ()
import tempfile
def save_file_to_db(file_id, filename, content):# 加载文档# relative_temp_file_path os.path.relpath(f./uploads/{filename})# print(relative_temp_file_path)loader PyPDFLoader(f./uploads/{filename})pages loader.load_and_split()# 文档切分text_splitter RecursiveCharacterTextSplitter(chunk_size200,chunk_overlap100,length_functionlen,add_start_indexTrue,)texts text_splitter.create_documents([page.page_content for page in pages[:4]])# 灌库embeddings OpenAIEmbeddings(modeltext-embedding-ada-002)db FAISS.from_documents(texts, embeddings)# 检索 top-1 结果retriever db.as_retriever(search_kwargs{k: 5})global rag_chain# Chainrag_chain ({question: RunnablePassthrough(), context: retriever}| prompt| model| StrOutputParser())app.route(/ask, methods[POST])
def ask_question():data request.jsonfile_id data.get(file_id)question data.get(question)print(file_id:, file_id, question:, question)content get_file_content_from_db(file_id, question)print(content:, str(content))return jsonify({status: success, answer: str(content)})def get_file_content_from_db(file_id, question):result rag_chain.invoke(question)return resultif __name__ __main__:app.run(debugTrue)
运行项目
部署与运行 前端 运行开发服务器 npm run serve后端 运行 Flask 应用 python app.py实现效果
选择md文件 上传成功 问答
Llama 2有多少参数Llama2Chat有哪些模型参数TrainingDetails在第几页 回答基于上传的LIama2.pdf文档。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/89743.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!