A Python project for query rewriting using LLMs and other methods.
Project description
为大模型应用测试提供Query 改写的工具:query rewrite
项目简介
大模型应用测试提供最需要的就是query改写,也有叫问题改写,query扩写等等,其实都是为了在有限的测试数据之下快速扩充测试数据,让测试数据更加丰富。 queryrewrite是就是一个提供如上功能的Python库,它提供了多种方法来rewrite和验证查询,以提高搜索和检索系统的性能。该项目支持使用大型语言模型(LLM)、词汇表替换和同义词替换等方法进行查询重写,并提供多种验证方法来确保重写后的查询保持原始语义。
安装
环境要求
- Python >= 3.10
安装步骤
# 克隆仓库
git clone https://github.com/yourusername/queryrewrite.git
cd queryrewrite
# 安装依赖
pip install -e .
或者直接通过pip安装:
pip install queryrewrite
功能介绍
Query Rewrite 项目提供以下主要功能:
- query改写:使用多种方法重写原始查询,生成语义相似但表达不同的查询变体
- 改写query验证和筛选:使用多种方法验证改写后的query,确保它们与原始query保持语义一致性,去除质量较差的改写
- LLM集成:支持与多种大型语言模型集成,如Ollama提供的模型
- 中文支持:特别优化了对中文文本的处理,包括分词和相似度计算
查询重写方法
1. LLM改写 (RewriteMethod.LLM)
利用大型语言模型(如Qwen、Llama等)重写查询。这种方法可以生成语义相似但表达方式不同的查询变体,有助于捕获用户意图的不同表达方式。
2. 词汇表改写 (RewriteMethod.GLOSSARY)
基于预定义的词汇表进行查询重写。词汇表包含同义词组,系统会使用这些同义词替换原始查询中的关键词,生成多个查询变体。这种方法适用于有明确领域词汇的场景。
3. 同义词改写 (RewriteMethod.SYNONYM)
使用LLM生成原始查询中关键词的同义词,然后用这些同义词替换原始查询中的关键词,生成多个查询变体。这种方法结合了LLM的语义理解能力和词汇替换的精确性。
查询验证方法
1. 无验证 (ValidationMethod.NONE)
不进行任何验证,直接返回所有重写后的查询。适用于已经确信重写质量的场景,或者需要最大化查询多样性的情况。
2. ROUGE-L和BLEU归一化验证 (ValidationMethod.ROUGE_L_BLEU_NORMALIZED)
使用ROUGE-L和BLEU分数来评估改写的query与原始query的相似度,并选择最佳平衡点。这种方法既考虑了语义保留又考虑了表达多样性(BLEU)。
3. 帕累托最优 (ValidationMethod.PARETO_OPTIMAL)
应用帕累托最优原则,选择在ROUGE-L和BLEU分数上都不被其他查询支配的查询。这种方法可以找到语义保留和表达多样性的最佳平衡点。
4. 最详细 (ValidationMethod.MOST_DETAILED)
选择最详细(通常是最长)的重写查询。这种方法假设更详细的查询通常包含更多信息,可能更好地捕获用户意图。
5. ROUGE-L + BLEU阈值过滤 (ValidationMethod.FILTER_BY_ROUGE_L_BLEU_THRESHOLDS)
根据预设的ROUGE-L和BLEU阈值过滤重写查询。只有同时满足ROUGE-L最小阈值(确保语义相似性)和BLEU最大阈值(确保表达多样性)的查询才会被保留。
6. LLM语义相似度 (ValidationMethod.LLM_SEMANTIC_SIMILARITY)
利用LLM评估改写query与原始query的语义相似度。这种方法利用LLM的语义理解能力,可以捕获更复杂的语义关系,但计算成本较高。
使用示例
以下是使用queryrewrite库的完整示例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This demo showcases the usage of the queryrewrite library.
"""
from queryrewrite.llm.ollama import OllamaLLM
from queryrewrite.rewriting.base import rewrite, RewriteMethod
from queryrewrite.validation.base import validate, ValidationMethod
from queryrewrite.utils.data_models import Query, Glossary
def main():
"""Main function to run the demo."""
# 1. 初始化LLM
# 这里假设你已经运行了Ollama实例,并加载了qwen3:8b模型
try:
llm = OllamaLLM(model="qwen3:8b")
except Exception as e:
print(f"Error initializing Ollama LLM: {e}")
print("Please ensure Ollama is running and the model is available.")
return
# 2. 定义输入查询
query: Query = {"query": "如何测试一个大型语言模型?", "reference": "大型语言模型的测试是一个复杂的过程,涉及多个层面。"}
# 3. 演示重写方法
print("--- Demonstrating Rewriting Methods ---")
# 方法1: LLM重写器
print("\n--- Method 1: LLM Rewriter ---")
try:
llm_rewritten = rewrite(method=RewriteMethod.LLM, query=query, llm=llm,thinking='/no_think')
print(f"LLM Rewritten Queries: {llm_rewritten}")
except Exception as e:
print(f"Error during LLM rewriting: {e}")
# 方法2: 词汇表重写器
print("\n--- Method 2: Glossary Rewriter ---")
glossary: Glossary = [
["测试", "评估", "评测"],
["大型语言模型", "大模型", "LLM"],
]
glossary_rewritten = rewrite(method=RewriteMethod.GLOSSARY, query=query, glossary=glossary)
print(f"Glossary Rewritten Queries: {glossary_rewritten}")
# 方法3: 同义词重写器
print("\n--- Method 3: Synonym Rewriter ---")
try:
synonym_rewritten = rewrite(method=RewriteMethod.SYNONYM, query=query, llm=llm,thinking='/no_think')
print(f"Synonym Rewritten Queries: {synonym_rewritten}")
except Exception as e:
print(f"Error during synonym rewriting: {e}")
# 4. 演示验证方法
print("\n--- Demonstrating Validation Methods ---")
# 我们将使用glossary_rewritten列表进行验证示例
rewritten_queries = glossary_rewritten
# 方法1: 无验证
print("\n--- Validation Method 1: No Validation ---")
no_validation_result = validate(
method=ValidationMethod.NONE,
rewritten_queries=rewritten_queries,
original_query=query["query"]
)
print(f"No Validation Result: {no_validation_result}")
# 方法2: ROUGE-L + BLEU归一化
print("\n--- Validation Method 2: ROUGE-L + BLEU Normalized ---")
rouge_bleu_result = validate(
method=ValidationMethod.ROUGE_L_BLEU_NORMALIZED,
rewritten_queries=rewritten_queries,
original_query=query["query"]
)
print(f"ROUGE-L + BLEU Normalized Result: {rouge_bleu_result}")
# 方法3: 帕累托最优
print("\n--- Validation Method 3: Pareto Optimal ---")
pareto_result = validate(
method=ValidationMethod.PARETO_OPTIMAL,
rewritten_queries=rewritten_queries,
original_query=query["query"]
)
print(f"Pareto Optimal Result: {pareto_result}")
# 方法4: 最详细
print("\n--- Validation Method 4: Most Detailed ---")
detailed_result = validate(
method=ValidationMethod.MOST_DETAILED,
rewritten_queries=rewritten_queries,
original_query=query["query"]
)
print(f"Most Detailed Result: {detailed_result}")
# 方法5: 根据ROUGE-L + BLEU阈值过滤
print("\n--- Validation Method 5: Filter by ROUGE-L + BLEU Thresholds ---")
filtered_result = validate(
method=ValidationMethod.FILTER_BY_ROUGE_L_BLEU_THRESHOLDS,
rewritten_queries=rewritten_queries,
original_query=query["query"]
)
print(f"Filtered Result: {filtered_result}")
# 方法6: LLM语义相似度
print("\n--- Validation Method 6: LLM Semantic Similarity ---")
try:
llm_similarity_result = validate(
method=ValidationMethod.LLM_SEMANTIC_SIMILARITY,
rewritten_queries=rewritten_queries,
original_query=query["query"],
llm=llm,
thinking='/no_think'
)
print(f"LLM Semantic Similarity Result: {llm_similarity_result}")
except Exception as e:
print(f"Error during LLM semantic similarity validation: {e}")
if __name__ == "__main__":
main()
如何扩展LLM
本项目设计了灵活的LLM接口,可以轻松扩展支持不同的大型语言模型。以下是如何添加OpenAI支持的示例。
1. 创建新的LLM实现类
首先,创建一个新的Python文件,例如openai.py,实现LLMBase抽象类:
# queryrewrite/llm/openai.py
from langchain_openai import ChatOpenAI
from queryrewrite.llm.base import LLMBase
class OpenAILLM(LLMBase):
"""LLM implementation for OpenAI models."""
def __init__(self, model: str = "gpt-3.5-turbo", api_key: str = None, temperature: float = 0.7):
"""
Initializes the OpenAILLM.
Args:
model: The name of the OpenAI model to use.
api_key: Your OpenAI API key.
temperature: Controls randomness. Higher values make output more random,
lower values make it more deterministic.
"""
self.model = model
self.api_key = api_key
self.temperature = temperature
self.llm = ChatOpenAI(
model=self.model,
openai_api_key=self.api_key,
temperature=self.temperature
)
def invoke(self, prompt: str) -> str:
"""Invoke the OpenAI model with a given prompt."""
response = self.llm.invoke(prompt)
return response.content
2. 安装必要的依赖
确保安装了OpenAI的依赖:
pip install langchain-openai openai
3. 使用新的LLM实现
现在,您可以在代码中使用OpenAI模型:
from queryrewrite.llm.openai import OpenAILLM
from queryrewrite.rewriting.base import rewrite, RewriteMethod
from queryrewrite.utils.data_models import Query
# 初始化OpenAI LLM
llm = OpenAILLM(
model="gpt-3.5-turbo",
api_key="your-openai-api-key", # 替换为您的API密钥
temperature=0.7
)
# 定义查询
query = {"query": "如何测试一个大型语言模型?", "reference": "大型语言模型的测试是一个复杂的过程,涉及多个层面。"}
# 使用OpenAI进行查询重写
rewritten_queries = rewrite(method=RewriteMethod.LLM, query=query, llm=llm)
4. 扩展其他LLM提供商
您可以使用相同的模式扩展支持其他LLM提供商,如百度文心一言、讯飞星火等。只需:
- 创建一个新的类,继承
LLMBase - 实现
__init__和invoke方法 - 安装相应的依赖
- 在您的代码中使用新的LLM实现
注意事项
- 使用LLM相关功能前,请确保已安装并运行相应的LLM服务(如Ollama)或配置正确的API密钥(如OpenAI)
- 对于中文查询,系统使用jieba进行分词处理,以提高相似度计算的准确性
- ROUGE-L和BLEU阈值可以根据具体应用场景进行调整
- 使用OpenAI等商业API时,请注意API使用成本和速率限制
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file queryrewrite-0.1.0.tar.gz.
File metadata
- Download URL: queryrewrite-0.1.0.tar.gz
- Upload date:
- Size: 20.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e98be195b42bec887fc7b108386445b2b490e9732ece7a9e4958dc25c200b3c
|
|
| MD5 |
ca9315a21a704534b531352744d19388
|
|
| BLAKE2b-256 |
f5a7fb8cb0d24153a5c92520d8756622f705a609f96b1edf684663ece9de0de1
|
File details
Details for the file queryrewrite-0.1.0-py3-none-any.whl.
File metadata
- Download URL: queryrewrite-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c34f07df5b07fcd34bc04987d11f18271dca3f6493249dbc6a9908d8fd6de43
|
|
| MD5 |
8edb3bbab260078dd6c7c1fd9e0036c9
|
|
| BLAKE2b-256 |
ae8ecb38110e9edc7ceccb07c2f1545c0b055bcd1f3e486f563e40b682de555b
|