Deepseek API+Python 测试用例一键生成与导出 V1.0.5工具,随着需求文档和接口文档的复杂性和长度不断增加,基于大模型生成测试用例的任务也变得更加挑战。尤其当文档内容过多时,大模型可能因输入长度限制而无法提供完整的回答。这种情况下,合理的分词策略不仅可以有效解决问题,还能提升生成过程的效率和准确性。
1. 为什么需要分块?
大模型(如 GPT 系列)通常对输入长度有严格限制。如果直接将超长的文档内容传递给大模型:
- 输入超限:模型会截断多余的输入,导致关键信息丢失。
- 结果不完整:输出内容可能因为未处理完所有输入而中断。
- 生成效率低:过长的输入可能导致生成时间显著增加。
通过将文档内容合理分块,不仅可以规避上述问题,还可以优化生成质量,将完整的测试用例输出整合起来。
** 1.1 常见分块策略**
在处理大模型输入时,输入分块是解决长文本或大数据量输入问题的重要方法。分块方法直接影响模型性能、计算效率以及结果的质量。以下是几种常见的输入分块方法及其比较,最后提出最优选择的建议。
1.1.1 滑动窗口分块
原理:
将输入按固定长度切分为多个块,每个块之间有部分重叠。滑动窗口的大小和重叠步长可以根据具体任务调整。
-
优点:
- 能捕捉到跨分块的上下文信息。
- 对于需要上下文连续性的任务(如问答、摘要)效果较好。
-
缺点:
- 计算成本高,因存在重叠,处理的文本量增加。
- 可能导致某些信息重复处理,增加冗余。
-
适用场景:
- 长文本情感分析。
- 长篇文档摘要生成。
- 文档问答任务。
1.1.2 固定长度分块
原理:
将输入按照固定长度(如模型的最大输入长度)切分为多个不重叠的片段,直接输入模型。
-
优点:
- 实现简单,计算效率高。
- 适合需要高吞吐量的任务。
-
缺点:
- 跨块的上下文信息可能丢失。
- 对于长距离依赖的任务效果较差。
-
适用场景:
- 文本分类任务。
- 信息抽取任务。
1.1.3 按语义分块
原理:
基于文本的语义结构(如段落、句子)进行切分,而不是固定长度。通常使用分句工具或自然语言处理技术进行分块。
-
优点:
- 分块更自然,能够保持语义完整性。
- 有效避免因切割位置不当导致的语义丢失。
-
缺点:
- 分块长度可能不均匀,处理时需注意填充或截断。
- 对模型输入的最大长度有一定要求。
-
适用场景:
- 文档摘要生成。
- 长文档的主题提取。
1.1.4. 动态分块
原理:
根据模型的最大输入长度动态调整分块长度,尽可能利用模型的输入容量。结合前后上下文信息,灵活切分。
-
优点:
- 更高效地利用模型的输入容量。
- 上下文保留更完整。
-
缺点:
- 实现复杂,需动态调整。
- 对计算资源要求较高。
-
适用场景:
- 多轮对话任务。
- 需要动态上下文处理的任务。
1.1.5 分层分块
原理:
首先按层次结构将输入切分成若干大块(如按章节或段落),然后针对每个大块再细分为小块,逐层输入模型。
-
优点:
- 保持全局语义信息。
- 分层的上下文信息利用较充分。
-
缺点:
- 实现复杂,需分层处理。
- 时间和计算成本较高。
-
适用场景:
- 多文档摘要。
- 长文档的分段问答。
1.1.6 方法比较
方法 | 上下文保留 | 计算效率 | 复杂度 | 适用场景 |
---|---|---|---|---|
滑动窗口分块 | 高 | 低 | 中 | 上下文相关任务 |
固定长度分块 | 低 | 高 | 低 | 高吞吐量任务 |
按语义分块 | 中 | 中 | 中 | 语义完整性要求高的任务 |
动态分块 | 高 | 中 | 高 | 灵活上下文需求的任务 |
分层分块 | 高 | 低 | 高 | 全局语义相关任务 |
最优选择建议
-
任务需要跨块上下文信息(如问答、摘要):
- 推荐方法:滑动窗口分块或动态分块。
滑动窗口更适合处理固定上下文长度的场景,而动态分块在需要灵活上下文处理时更优。
- 推荐方法:滑动窗口分块或动态分块。
-
任务对语义完整性要求高(如摘要、主题提取):
- 推荐方法:按语义分块。
保持语义一致性,适合需要精准语义理解的任务。
- 推荐方法:按语义分块。
-
大规模文本分类或信息抽取任务(高吞吐量):
- 推荐方法:固定长度分块。
简单高效,适合对上下文依赖性较低的任务。
- 推荐方法:固定长度分块。
-
需要全局上下文信息(如多文档处理):
- 推荐方法:分层分块。
适合需要分层次分析的复杂任务。
- 推荐方法:分层分块。
2. 分块策略选择
根据常见分块策略,以下是适合需求文档和接口文档分块的策略:
2.1 固定长度分块
将文档内容按固定的字符数或单词数进行分块。例如,每 1000 个字符或每 200 个汉字为一个块。这种方式简单直接,适合一般文档。
优点:
- 实现简单,易于控制每块的大小。
- 对于无特定逻辑的文档内容十分有效。
缺点:
- 分块可能会截断上下文逻辑,导致语义不连贯。
2.2 基于内容的分块
将文档按内容结构(如段落、标题、接口定义块)进行分割。例如,需求文档可以按功能模块分块,接口文档可以按接口名称分块。
优点:
- 保留了文档逻辑结构,语义连贯性好。
- 更适合复杂的文档内容。
缺点:
- 实现相对复杂,需要根据文档内容的结构进行解析。
2.3 滑动窗口分块
在固定长度分块的基础上,添加一定的重叠区域。例如,每次分块包含上一块的最后 200 个字符,确保上下文连续。
优点:
- 避免了上下文丢失问题。
- 可用于需要跨块关联的文档内容。
缺点:
- 会产生重复的内容,处理时需要去重。
2.4 推荐策略
基于需求和接口文档的特点,我们推荐组合使用 固定长度分块 和 滑动窗口分块:
- 固定长度分块:适合大多数文档,快速分割内容。
- 滑动窗口分块:适合需要上下文连续的内容(如接口定义中的依赖关系)。
3. 分块实现:Python 代码
以下是 Python 的分块实现代码,结合了固定长度和滑动窗口策略,适合处理需求文档和接口文档内容。
3.1 分块函数实现
def chunk_text(text, chunk_size=1000, overlap=200):"""将文本按固定长度分块,同时添加滑动窗口重叠。参数:- text (str): 输入的长文本内容- chunk_size (int): 每块的最大字符数- overlap (int): 相邻块的重叠字符数返回:- list: 分块后的文本列表"""print("开始分块...")chunks = []start = 0text_length = len(text)while start < text_length:end = min(start + chunk_size, text_length)chunk = text[start:end]chunks.append(chunk)# 滑动窗口:下一块的起始位置向后移动 chunk_size - overlapstart += chunk_size - overlapprint(f"分块完成,共生成 {len(chunks)} 个块。")return chunks
3.2 分块后的循环调用大模型
将分块后的内容逐块传递给大模型,并汇总结果。这一过程确保了所有内容都能够完整处理。
def process_chunks_with_model(chunks, model_call_function):"""循环处理分块内容并汇总结果。参数:- chunks (list): 分块后的文本列表- model_call_function (function): 调用大模型的函数,接受单个块,返回结果返回:- str: 汇总后的完整结果"""results = []for i, chunk in enumerate(chunks):print(f"正在处理第 {i + 1} 个块...")result = model_call_function(chunk) # 调用大模型处理单个块results.append(result)# 将所有块的结果整合为一个完整的字符串combined_result = "\n".join(results)print("处理完成,已整合所有分块结果。")return combined_result
3.3 示例:对读取到的需求文档内容进行分块处理
以下代码展示了一个完整的流程,鉴于小工具已读取到了文档内容,这里只对文档的内容进行分块即可,从读取需求文档到分块调用大模型,再到整合输出结果。
def run(self):try:# todo 此处加入分块处理# 分块内容context_chunks = self.chunk_text(self.context)all_result_str = ""for context_chunk in context_chunks:# 调用大模型result = self.generate_cases(context_chunk)if result is not None and isinstance(result, str):all_result_str += resultelse:print(f"{context_chunk}推理结果异常!")if 'json' in all_result_str:all_result_str = re.search(r"```json(.*)```", all_result_str, re.DOTALL)# 拼接成一个完整的 JSON 数组try:# 将每个 JSON 字符串解析为字典json_objects = [json.loads(js) for js in all_result_str]# 将多个字典合并为一个 JSON 数组(或其他需要的结构)combined_json = json.dumps(json_objects, indent=4)print("Combined JSON:")print(combined_json)except json.JSONDecodeError as e:print(f"Error parsing JSON: {e}")# if all_result_str:# json_str = all_result_str.group(1)# result = json_strself.finished.emit(combined_json)except Exception as e:self.error.emit(str(e))
3.4 示例:调用大模型函数
以下是一个模拟的大模型调用函数,可替换为实际的 API 调用代码。
def generate_cases(self, chunk_data):# 初始化OpenAI客户端client = OpenAI(# 如果没有配置环境变量,请用百炼API Key替换:api_key="sk-xxx"# api_key='sk-xxx',api_key='sk-xxx', # todo 此处需更换base_url="https://dashscope.aliyuncs.com/compatible-mode/v1")# chunked_context_list = self.chunk_data(self.context, chunk_size=2000) # 根据需要调整 chunk_sizeall_results = []reasoning_content = "" # 定义完整思考过程answer_content = "" # 定义完整回复is_answering = False # 判断是否结束思考过程并开始回复# 创建聊天完成请求completion = client.chat.completions.create(model="deepseek-r1", # 此处以 deepseek-r1 为例,可按需更换模型名称messages=[{'role': 'user', 'content': f'所在行业: {self.job_area};'f'文档内容: {chunk_data}; 'f'生成的用例类型: {self.func_type}; 'f'用例设计方法: {self.design_method}; 'f'提示词:{self.prompt};'}],stream=True,# 解除以下注释会在最后一个chunk返回Token使用量# stream_options={# "include_usage": True# })print("\n" + "=" * 20 + "思考过程" + "=" * 20 + "\n")for chunk in completion:# 如果chunk.choices为空,则打印usageif not chunk.choices:print("\nUsage:")print(chunk.usage)else:delta = chunk.choices[0].delta# 打印思考过程if hasattr(delta, 'reasoning_content') and delta.reasoning_content != None:print(delta.reasoning_content, end='', flush=True)reasoning_content += delta.reasoning_contentelse:# 开始回复if delta.content != "" and not is_answering:print("\n" + "=" * 20 + "完整回复" + "=" * 20 + "\n")is_answering = True# 打印回复过程print(delta.content, end='', flush=True)answer_content += delta.contentreturn answer_content
4. 效果展示
4.1 示例输入
假设读取的需求文档内容如下:
这是一个示例需求文档,内容较长,因此需要分块处理。
文档包含多个功能模块,每个模块都有其独特的逻辑和流程。
需要设计全面的测试用例,包括正常场景、异常场景和边界场景。
接口文档部分定义了请求方法、URL、参数、响应格式等。
...
4.2 分块结果
分块后,每块内容如下:
- 块 1:
这是一个示例需求文档,内容较长,因此需要分块处理...
- 块 2:
文档包含多个功能模块,每个模块都有其独特的逻辑和流程...
- …
4.3 汇总结果
调用大模型后,整合所有块的处理结果为完整的输出文档,确保内容无遗漏。
5. 总结
在测试用例生成工具中,合理的分块策略是确保大模型完整回答的关键。在本次优化中:
- 我们结合固定长度分块和滑动窗口分块,既保证了上下文的连贯性,又避免了模型输入超限的问题。
- 分块后的内容通过循环传递给大模型,逐步生成结果,最终整合为完整的测试用例输出。
- 提供了 Python 的分块实现代码,适合测试工程师快速集成到现有工具中。
通过这一优化,Deepseek API+Python 测试用例一键生成与导出 V1.0.5工具在处理超长文档时更加高效、稳定,是测试工程师设计高质量测试用例的绝佳助手!