基于需求文档、设计文档、测试用例的测试答疑助手
基于需求文档、设计文档、测试用例的测试答疑助手
- 一、简介
- 二、示例使用数据
- 三、实践演练
- 1、实战设计思路
- 2、安装依赖
- 3、代码实现
- 3.1、通过环境变量设置API Token,以及相关依赖的导入:
- 3.2、处理源文档,将其切片处理:
- 3.3、如果数据存在,则加载使用,如果不存在,则写入:
一、简介
在本章节,将基于 LangChain 实现一个 mini 的实战案例。这次实战主要完成的任务,就是设计一个测试答疑助手,这个测试答疑助手的主要功能为基于本地的文档和数据,回答给出的自然语言问题,比如一些数据的统计,查找、组合。
二、示例使用数据
测试用例.md
# 测试人论坛测试用例
## 1. 用户模块
### 1.1 用户注册
#### 用例描述
确保用户能够正常注册。
#### 前置条件
- 用户未注册
#### 步骤
1. 打开注册页面。
2. 输入用户名test001
3. 输入密码000000
4. 输入电子邮箱test001@ceshiren.com
5. 点击“注册”按钮。
#### 断言
- 用户电子邮箱test001@ceshiren.com应收到注册成功的通知。
- 数据库中应有用户名test001\密码000000的用户信息
- 验证用户信息是否一致
### 1.2 用户注册失败
#### 用例描述
异常数据不能注册。
#### 前置条件
- 用户未注册
#### 步骤
1. 打开注册页面。
2. 输入用户名test002
3. 输入密码aa
4. 输入电子邮箱test002@ceshiren.com
5. 点击“注册”按钮。
#### 断言
- 注册失败,密码长度不符合要求
### 1.3 用户注册失败
#### 用例描述
异常数据不能注册。
#### 前置条件
- 用户未注册
#### 步骤
1. 打开注册页面。
2. 输入用户名test003
3. 输入密码¥¥
4. 输入电子邮箱test003@ceshiren.com
5. 点击“注册”按钮。
#### 断言
- 注册失败,密码格式不符合要求
### 1.4 用户注册失败
#### 用例描述
异常数据不能注册。
#### 前置条件
- 用户未注册
#### 步骤
1. 打开注册页面。
2. 输入用户名test004
3. 不输入密码
4. 输入电子邮箱test004@ceshiren.com
5. 点击“注册”按钮。
#### 断言
- 注册失败,密码为必填项,无法提交
---
### 1.5 用户登录
#### 用例描述
验证已注册用户能够正常登录。
#### 前置条件
- 用户已注册
#### 步骤
1. 打开登录页面。
2. 输入用户名test001
3. 输入密码000000
4. 点击“登录”按钮。
#### 断言
- 用户应被重定向到论坛的主页。
- 用户的用户名test001应显示在页面的顶部。
---
## 2. 帖子模块
### 2.1 创建帖子
#### 用例描述
确保已登录的用户可以创建新帖子。
#### 前置条件
- 用户已登录
#### 步骤
1. 点击“创建新帖子”按钮。
2. 输入帖子标题和内容。
3. 点击“提交”按钮。
#### 断言
- 用户应被重定向到新帖子的页面。
- 帖子的内容和标题应与用户输入的内容和标题相匹配。
---
### 2.2 编辑帖子
#### 用例描述
验证帖子的作者可以编辑其帖子。
#### 前置条件
- 用户已登录并已创建帖子。
#### 步骤
1. 打开自己的帖子页面。
2. 点击“编辑”按钮。
3. 修改标题和/或内容。
4. 点击“保存”按钮。
#### 断言
- 帖子页面应显示更新的标题和内容。
- 数据库中的帖子信息应与更新的内容相匹配。
---
## 3. 评论模块
### 3.1 添加评论
#### 用例描述
确保用户可以为帖子添加评论。
#### 前置条件
- 用户已登录
#### 步骤
1. 打开任意帖子页面。
2. 在评论框中输入评论内容。
3. 点击“提交评论”按钮。
#### 断言
- 评论应显示在帖子下方。
- 数据库中应有新的评论记录。
---
### 3.2 删除评论
#### 用例描述
验证用户可以删除自己的评论。
#### 前置条件
- 用户已登录并已评论。
#### 步骤
1. 找到自己的评论。
2. 点击评论旁边的“删除”按钮。
#### 断言
- 评论应从帖子页面中消失。
- 数据库中的评论记录应被删除。
---
这只是一些基本的测试用例。在实际测试过程中,可能需要根据实际的功能实现和需求来增加更多的测试用例,以确保系统的完整性和稳定性。
设计文档.md
# 测试人论坛代码架构设计文档
## 1. 介绍
这是一个针对测试技术的论坛,旨在为测试工程师提供一个交流技术、分享经验和学习的平台。
## 2. 系统概述
系统包含以下模块:
1. 用户模块
2. 论坛帖子模块
3. 评论模块
4. 搜索模块
5. 通知模块
6. 管理后台模块
## 3. 数据库设计
### 3.1 用户表 `users`
| 字段名 | 类型 | 描述 |
| ------------- | -------------- | ----------------- |
| id | INT (AUTO_INCREMENT) | 用户ID |
| username | VARCHAR(255) | 用户名 |
| password | VARCHAR(255) | 加密密码 |
| email | VARCHAR(255) | 邮箱 |
| registration_date | DATETIME | 注册日期 |
| last_login | DATETIME | 最后登录时间 |
| ... | ... | ... |
### 3.2 帖子表 `posts`
| 字段名 | 类型 | 描述 |
| ------------- | ------------- | ----------------- |
| id | INT (AUTO_INCREMENT) | 帖子ID |
| title | VARCHAR(255) | 帖子标题 |
| content | TEXT | 帖子内容 |
| author_id | INT | 作者ID(外键) |
| creation_date | DATETIME | 创建日期 |
| ... | ... | ... |
### 3.3 评论表 `comments`
| 字段名 | 类型 | 描述 |
| ------------- | ------------- | ----------------- |
| id | INT (AUTO_INCREMENT) | 评论ID |
| content | TEXT | 评论内容 |
| author_id | INT | 作者ID(外键) |
| post_id | INT | 帖子ID(外键) |
| creation_date | DATETIME | 创建日期 |
| ... | ... | ... |
... 更多表 ...
## 4. 代码架构
### 4.1 用户模块
```pseudo
interface IUserService {
register(User user): void;
login(String username, String password): User;
logout(User user): void;
}
class UserService implements IUserService {
register(User user) {
// TODO: Implement registration logic
}
login(String username, String password): User {
// TODO: Implement login logic
}
logout(User user) {
// TODO: Implement logout logic
}
}
需求文档
# 需求文档
### 项目概述
本需求文档旨在描述一个名为“测试人论坛”的在线技术论坛平台,该论坛将为测试人员提供技术交流、答疑咨询等功能,并吸引众多技术专家参与讨论和分享经验。
### 目标用户群体
1. 测试人员:包括软件测试工程师、质量保证工程师、自动化测试工程师等,他们需要一个专业的技术交流平台来获取最新的测试技巧和最佳实践。
2. 技术专家:包括软件开发工程师、架构师、系统管理员等,他们可以成为论坛上的技术顾问或解答其他测试人员的问题。
### 功能要求
1. 注册与登录:用户可以通过注册账号后登录到论坛,并管理个人资料。
2. 主题分类:用户可以在论坛上创建新的主题,并将其分配到相应的类别中(如测试工具、性能测试、自动化测试等)。
3. 发布帖子:用户可以撰写问题、回答他人的问题或者分享自己的经验,同时可以选择将其标记为私密或公开可见。
4. 搜索功能:用户可以根据关键字或其他条件搜索相关话题或帖子。
5. 通知订阅:用户可以关注感兴趣的主题或作者,并在新帖子发布时收到通知。
6. 点赞和评论:用户可以对帖子进行点赞和评论,以表达对其内容的评价和意见。
7. 私信功能:用户可以向其他用户发送私信,以便私下交流或寻求帮助。
8. 积分和等级制度:用户通过积极参与论坛活动获得积分,达到一定积分阈值后可升级至不同的等级,享受相应特权。
9. 社区管理:管理员可以设置权限,控制哪些用户可以发布帖子、编辑主题等操作。
10. 数据分析报告:管理员可以查看论坛的访问量、热门话题、发帖量等统计数据,用于优化论坛运营策略。
### 技术要求
1. 支持Discourse开源框架,确保论坛能够稳定运行且具有良好的扩展性。
2. 具备安全防护措施,保护用户隐私信息不被泄露。
3. 具备高可用性和负载均衡能力,确保论坛在高峰期仍能保持良好响应速度。
4. 支持多语言界面,方便不同地区用户的使用。
5. 具备移动端适配,用户可以在手机和平板电脑上浏览论坛。
### 非功能要求
1. 界面简洁明了,易于导航和使用。
2. 提供友好的用户反馈机制,例如错误提示、建议改进等。
3. 定期更新和维护,修复已知漏洞和bug,提升用户体验。
4. 与其他社交媒体平台集成,例如Twitter、Facebook等,增加用户粘性。
### 时间表
1. 需求分析阶段:确定论坛的功能需求、用户群体以及技术要求,制定详细的需求文档。
2. 设计阶段:根据需求文档,设计论坛的整体结构和各个模块的功能流程。
3. 开发阶段:按照设计阶段的结果,开始实现论坛的核心功能,并进行单元测试和集成测试。
4. 上线阶段:完成开发工作后,进行全面的系统测试,确保论坛能够正常运行并且满足所有功能需求。
5. 运维阶段:负责论坛的日常维护和监控,及时解决用户反馈的问题,保障论坛的稳定性和可靠性。
### 总结
测试人论坛的目标是为测试人员提供一个专业技术交流平台,吸引众多技术专家参与讨论和分享经验。
三、实践演练
1、实战设计思路
2、安装依赖
安装依赖 chromadb,chromadb是一个简单快捷的向量数据库,为了减少对embedding模型的请求次数,设置数据保存的物理位置,这样多次运行代码也不会重复请求模型转换向量:
pip install chromadb
- embedding: 相当于一个“桥梁” —— 翻译:把图片,文字,视频以及音频全部转换为数字,并且包含了数据的信息,使得大模型都能”懂“,能利用这些数字去做训练和推理。
- 向量:向量本身是一组数字,但是在几何上,向量的各个数字组成了多维的数组空间,向量的每个维度代表该空间的·一个不同的特征或者属性。
- 向量数据库:专门用于存储和管理向量数据的数据库,能对向量数据进行高效的操作。
3、代码实现
3.1、通过环境变量设置API Token,以及相关依赖的导入:
# 一些LangChain的依赖导入
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import MarkdownHeaderTextSplitter
from langchain.vectorstores import Chroma
# 加载openai 的 API Tokenfrom utils.data_load import get_auth
# 通过环境变量设置API Token,因为代码中的部分模型调用实例无法直接传递参数,需要通过环境变量设置的方式将token传递给自动构建的OpenAI请求
import os
os.environ['OPENAI_API_KEY'] = 'open_ai_token'
os.environ['OPENAI_API_BASE'] = 'open_ai_url'
3.2、处理源文档,将其切片处理:
# 定义一个函数,用于加载本地文件中的文本
def load_text_from_file(path: str) -> str:
return open(path, encoding='utf-8').read()
# 根据测试用例文档中的结构,定义一个MarkdownHeaderTextSplitter实例,用于将markdown文档切分为文本片段,方便后续embedding处理和向量数据库的构建
testcase_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[("##", "模块名称"), ("###", "用例名称")])
docs = testcase_splitter.split_text(load_text_from_file(path="docs/测试用例.md"))
# 同样处理设计文档,因为设计文档中的结构与测试用例文档不一致,所以要新定义一个MarkdownHeaderTextSplitter实例
design_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[("##", "功能名称"), ("###", "模块名称")])
docs += design_splitter.split_text(load_text_from_file(path="docs/设计文档.md"))
# 同理,处理需求文档
prd_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=[("###", "功能名称")])
docs += prd_splitter.split_text(load_text_from_file(path="docs/需求文档.md"))
# 将切分后的文本片段输出,可以查看切分结果,和里面附带的数据信息
for doc in docs:
print(doc)
3.3、如果数据存在,则加载使用,如果不存在,则写入:
persist_directory = 'chroma'
# 读取数据
if os.path.isdir(persist_directory):
vectordb = Chroma(persist_directory=persist_directory, embedding_function=OpenAIEmbeddings())
else:
# 将切分后的数据,通过OpenAIEmbeddings实例,转换为向量数据,
# 并保存到向量数据库中,持久化到本地指定目录下
vectordb = Chroma.from_documents(
documents=docs,
embedding=OpenAIEmbeddings(),
persist_directory=persist_directory
)
3.4、将向量数据库中检索到的文本片段以及提示词组成为 prompt,向大模型获取返回信息:
# 设定最终提出的问题
question = "问题:请统计出用户注册用例中,用到的所有用户名、密码、电子邮箱数据,并将它们列成一个表格"
# 从向量数据库中找到相似度最高的k条文本片段数据
answer_docs = vectordb.similarity_search(query=question, k=4)
# ChatGPT3.5大模型调用实例
llm = ChatOpenAI(temperature=0.0)
# 将向量数据库中检索到的文本片段组装成字符串,作为输入的数据源
resource_doc = "".join([chunk.page_content for chunk in answer_docs])
# 将数据源字符串和问题组装成最终请求大模型的字符串
final_llm_text = f"{resource_doc} {question}"
# 通过大模型获取字符串的回答信息
response = llm.call_as_llm(message=final_llm_text)
print(f"回答结果:\n{response}")