Veblen34's picture
Upload folder using huggingface_hub
cd6775d verified
Raw
History Blame Contribute Delete
15.3 kB
from transformers import pipeline
import torch
import pandas as pd
import sys
import os
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'document_retrieval', 'Decompose_retrieval'))
import ragqa_paths # [ragqa] portable paths
from vllm import LLM, SamplingParams
from transformers import AutoTokenizer
from openai import OpenAI
from manyqa_text import *
import requests
import pickle
from tqdm import tqdm
import os
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
os.environ['https_proxy'] = 'http://127.0.0.1:7890/'
os.environ['http_proxy'] = 'http://127.0.0.1:7890/'
# os.environ['CUDA_VISIBLE_DEVICES'] = '1'
dataset = 'manyqa_text'
def call_llama3_single_prompt(
inputs, model="Llama-3.1-8B-Instruct", max_decode_steps=100, temperature=0.0
):
inputs_ls = []
if isinstance(inputs, str):
messages = [
{"role": "user", "content": inputs},
]
inputs_ls.append(tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True))
else:
for idx in range(len(inputs)):
inputs_ls.append(tokenizer.apply_chat_template(inputs[idx], tokenize=False, add_generation_prompt=True))
# ans = get_vllm_llama(temperature, max_decode_steps, inputs_ls)
results = client.completions.create(
model=ragqa_paths.LLAMA_MODEL,
max_tokens=max_decode_steps,
temperature=0,
prompt=inputs_ls,
timeout = None
)
ans = []
for item in results.choices:
ans.append([item.text.strip()])
return ans
def call_llama3_func(
inputs, model="Llama-3.1-8B-Instruct", max_decode_steps=100, temperature=0.0
):
print(max_decode_steps, temperature)
output = call_llama3_single_prompt(
inputs,
model=model,
max_decode_steps=max_decode_steps,
temperature=temperature
)
if isinstance(inputs, str):
return output[0]
else:
return output
def get_supervised_decom(queries_ls):
prompts = []
for query in queries_ls:
prompts.append([{"role": "user", "content": query}])
prompts_tokened = [tokenizer.apply_chat_template(x, tokenize=False, add_generation_prompt=True) for x in prompts]
results = client.completions.create(
model="supervised",
max_tokens=512,
temperature=0,
prompt=prompts_tokened,
timeout = None
)
ans = []
for item in results.choices:
ans.append([[x.strip() for x in item.text.split('|')]])
return ans
def get_ans(queries_ls, passages):
prompts = []
for i in range(len(queries_ls)): # Please answer the question to the best of your knowledge, even if the context does not directly provide the information. Use any relevant knowledge you have to provide a helpful answer. # "You are a helpful assistant. answer the question according to the context." "You are a helpful assistant. Please answer the question to the best of your knowledge, even if the context does not directly provide the information. Use any relevant knowledge you have to provide a helpful answer."
prompts.append([
{"role": "system", "content": "You are a helpful assistant. answer the question according to the context."},
{"role": "user", "content": 'Context: ' + '\n'.join(passages[i][:3])},
{"role": "user", "content": 'Question: ' + queries_ls[i]},
])
pred_ls = [row[0] for row in call_llama3_func(prompts, max_decode_steps=100)]
return pred_ls
def hit_score(passages_ls, anspids, k):
assert len(passages_ls) == len(anspids)
cnt = 0
for i in range(len(passages_ls)):
# print(len(passages_ls[i]))
# 获取前k个检索结果
retrieved_topk = passages_ls[i][:k]
# 将检索结果和答案都转换为小写以进行不区分大小写的匹配
retrieved_topk = [p.strip().lower() for p in retrieved_topk]
ans_raw = anspids[i]
# 检查每个可能的答案
for ans in ans_raw:
ans = ans.strip().lower()
# 如果答案在任何一个检索结果中出现
if any(passage in ans for passage in retrieved_topk):
cnt += 1
break
return cnt / len(passages_ls)
def hit_ls(passages_ls, anspids, k):
assert len(passages_ls) == len(anspids)
ans_ls = []
for i in range(len(passages_ls)):
hit = 0
retrieved_topk = passages_ls[i][:k]
# 将检索结果和答案都转换为小写以进行不区分大小写的匹配
retrieved_topk = [p.strip().lower() for p in retrieved_topk]
ans_raw = anspids[i]
# 检查每个可能的答案
for ans in ans_raw:
ans = ans.strip().lower()
# 如果答案在任何一个检索结果中出现
if any(ans in passage for passage in retrieved_topk):
hit = 1
break
ans_ls.append(hit)
return ans_ls
import re
import csv
from io import StringIO
def parse_string(s):
s = s.strip()
if s.startswith('[') and s.endswith(']'):
# 处理列表结构
inner = s[1:-1].strip()
# 将单引号包裹的元素替换为双引号包裹,并转义内部双引号
pattern = re.compile(r"'((?:[^'\\]|\\.)*?)'")
def replace(match):
content = match.group(1)
content = content.replace('"', r'\"')
return f'"{content}"'
new_inner = pattern.sub(replace, inner)
# 使用 csv.reader 解析处理后的内容
csv_reader = csv.reader(
StringIO(new_inner),
quotechar='"',
escapechar='\\',
skipinitialspace=True
)
try:
return next(csv_reader)
except StopIteration:
return []
else:
# 处理单个字符串,包裹为双引号并转义内部双引号
content = s.replace('"', r'\"')
csv_reader = csv.reader(
StringIO(f'"{content}"'),
quotechar='"',
escapechar='\\'
)
try:
return next(csv_reader)
except StopIteration:
return [s]
def cover_em(pred_ls, ans_ls):
assert len(pred_ls) == len(ans_ls)
cnt = 0
score_ls = [] # 用于记录每个查询的正确性
for idx in range(len(pred_ls)):
pred = pred_ls[idx].lower()
ans = str(ans_ls[idx])
correct = 0 # 默认为错误
if ans.lower() in pred:
cnt += 1
correct = 1
score_ls.append(correct)
return cnt/len(pred_ls), score_ls
def supervised_method():
cache_path = ragqa_paths.dataset_file(dataset, "s_cache.pkl")
if os.path.exists(cache_path):
with open(cache_path, 'rb') as f:
sub_query_str_l = pickle.load(f)
print("Loaded cached subqueries")
else:
sub_query_str_l = get_supervised_decom(raw_queries)
with open(cache_path, 'wb') as f:
pickle.dump(sub_query_str_l, f)
print("Saved new subqueries to cache")
passages_ls = get_ir_result(raw_queries, sub_query_str_l)
print(f"hit@1 :{hit_score(passages_ls, ans_pids, 1)}")
print(f"hit@2 :{hit_score(passages_ls, ans_pids, 2)}")
print(f"hit@3 :{hit_score(passages_ls, ans_pids, 3)}")
print(f"hit@20 :{hit_score(passages_ls, ans_pids, 20)}")
print(f"hit@100 :{hit_score(passages_ls, ans_pids, 100)}")
passages_ls = [item[:3] for item in passages_ls]
pred_ls = get_ans(raw_queries, passages_ls)
return cover_em(pred_ls, true_answers)
def dense_method():
sub_query_str_l = [ [[raw]]for raw in raw_queries]
passages_ls = get_ir_result(raw_queries, sub_query_str_l)
print(f"hit@1 :{hit_score(passages_ls, ans_pids, 1)}")
print(f"hit@2 :{hit_score(passages_ls, ans_pids, 2)}")
print(f"hit@3 :{hit_score(passages_ls, ans_pids, 3)}")
print(f"hit@20 :{hit_score(passages_ls, ans_pids, 20)}")
print(f"hit@100 :{hit_score(passages_ls, ans_pids, 100)}")
passages_ls = [item[:3] for item in passages_ls]
pred_ls = get_ans(raw_queries, passages_ls)
return cover_em(pred_ls, true_answers)
def unsupervised_method():
sub_query_str_l = []
for query in tqdm(raw_queries):
url = 'http://127.0.0.1:50002/execute?query='+query
response = requests.get(url=url)
res_dic = response.json()
sub_query_str_l.append([res_dic['text']])
passages_ls = sentence_search(raw_queries, sub_query_str_l)
print(f"hit@1 :{hit_score(passages_ls, ans_pids, 1)}")
print(f"hit@2 :{hit_score(passages_ls, ans_pids, 2)}")
print(f"hit@3 :{hit_score(passages_ls, ans_pids, 3)}")
print(f"hit@20 :{hit_score(passages_ls, ans_pids, 20)}")
print(f"hit@100 :{hit_score(passages_ls, ans_pids, 100)}")
passages_ls = [item[:3] for item in passages_ls]
pred_ls = get_ans(raw_queries, passages_ls)
return cover_em(pred_ls, true_answers)
def iclfeed_method():
cache_path = ragqa_paths.dataset_file(dataset, "icl_cache.pkl")
if os.path.exists(cache_path):
with open(cache_path, 'rb') as f:
sub_query_str_l = pickle.load(f)
print("Loaded cached subqueries")
else:
sub_query_str_l = []
for query in tqdm(raw_queries):
url = 'http://127.0.0.1:50003/execute?query='+query
response = requests.get(url=url)
res_dic = response.json()
sub_query_str_l.append([res_dic['text']])
# 保存生成的子查询
with open(cache_path, 'wb') as f:
pickle.dump(sub_query_str_l, f)
print("Saved new subqueries to cache")
# passages_ls = get_ir_result(raw_queries, sub_query_str_l)
passages_ls = sentence_search(raw_queries, sub_query_str_l)
print(f"hit@1 :{hit_score(passages_ls, ans_pids, 1)}")
print(f"hit@2 :{hit_score(passages_ls, ans_pids, 2)}")
print(f"hit@3 :{hit_score(passages_ls, ans_pids, 3)}")
print(f"hit@20 :{hit_score(passages_ls, ans_pids, 20)}")
print(f"hit@100 :{hit_score(passages_ls, ans_pids, 100)}")
passages_ls = [item[:3] for item in passages_ls]
pred_ls = get_ans(raw_queries, passages_ls)
return cover_em(pred_ls, true_answers)
def sentence_search(queries, questions_ls):
passage_ls = []
for idx in tqdm(range(len(questions_ls))):
top_100_passages = []
query = questions_ls[idx]
payload = {
"query" : queries[idx],
"sub_query": query,
"k": 100
}
response = requests.post(
'http://localhost:8220/api/search',
json=payload
)
for i in range(len(response.json()['topk'])):
top_100_passages.append(response.json()['topk'][i]['text'])
passage_ls.append(top_100_passages)
return passage_ls
def colbert_search(query_item):
url = 'http://localhost:8895/api/search?query='+query_item+'&k=100'
response = requests.get(url=url)
res_dic = response.json()
corpus_list_topk = res_dic['topk']
# print(len(corpus_list_topk))
passage_ls = []
for i in range(min(100, len(corpus_list_topk))):
passage_ls.append(corpus_list_topk[i]['text'])
return passage_ls
def colbert_method():
passage_ls = []
for query in tqdm(raw_queries):
passage_ls.append(colbert_search(query))
print(f"hit@1 :{hit_score(passage_ls, ans_pids, 1)}")
print(f"hit@2 :{hit_score(passage_ls, ans_pids, 2)}")
print(f"hit@3 :{hit_score(passage_ls, ans_pids, 3)}")
print(f"hit@20 :{hit_score(passage_ls, ans_pids, 20)}")
print(f"hit@100 :{hit_score(passage_ls, ans_pids, 100)}")
passage_ls = [item[:3] for item in passage_ls]
pred_ls = get_ans(raw_queries, passage_ls)
score, score_ls = cover_em(pred_ls, true_answers)
from datetime import datetime
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
log_data = {
'raw_query': raw_queries,
'true_answer': true_answers,
'predicted_answer': pred_ls,
'acc' : score_ls,
'ir_hit' : hit_ls(passage_ls, ans_pids, 1)
}
log_df = pd.DataFrame(log_data)
log_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logs", f"colbert_method_log_{timestamp}.csv")
log_df.to_csv(log_path, index=False, encoding='utf-8-sig')
print(f"日志已保存至: {log_path}")
return score
def gen_prompt():
prompts = []
for query in raw_queries:
prompt = []
prompt.append({"role": "system", "content": """"Given the input query, break it down into meaningful tokens like ColBERT. Ensure the tokens retain the key semantic components. Provide the output as a comma-separated list. Query: '{query}' Tokens:"""})
prompt.append({"role": "user", "content": "Query: Victoria Hong Kong has many what type of buildings?"})
prompt.append({"role": "assistant", "content": "Victoria, Hong, Kong, has, many, what, type, of, buildings,?"})
prompt.append({"role": "user", "content": f"Query: {query}" })
prompts.append(prompt)
return prompts
def sentence_colbert():
tmp = gen_prompt()
raw_op_prompts = call_llama3_func(tmp)
sub_queries_ls= []
for idx in range(len(raw_queries)):
tmp_ls = raw_op_prompts[idx][0].replace("\n", "").split(",")
tmp_ls = [list(set([item.strip() for item in tmp_ls if item.strip() and item.strip() in raw_queries[idx]]))]
if len(tmp_ls[0]) == 0:
tmp_ls = [[raw_queries[idx]]]
sub_queries_ls.append(tmp_ls)
passages_ls = get_ir_result(raw_queries, sub_queries_ls)
print(f"hit@1 :{hit_score(passages_ls, ans_pids, 1)}")
print(f"hit@2 :{hit_score(passages_ls, ans_pids, 2)}")
print(f"hit@20 :{hit_score(passages_ls, ans_pids, 20)}")
print(f"hit@100 :{hit_score(passages_ls, ans_pids, 100)}")
passages_ls = [item[:3] for item in passages_ls]
pred_ls = get_ans(raw_queries, passages_ls)
return cover_em(pred_ls, true_answers)[0]
if __name__ == '__main__':
dataset_path = ragqa_paths.dataset_file(dataset, f"{dataset}_test.csv")
tokenizer = AutoTokenizer.from_pretrained(ragqa_paths.LLAMA_MODEL)
client = OpenAI(api_key="0",base_url="http://127.0.0.1:50001/v1")
raw_data = pd.read_csv(dataset_path, header=0)
raw_data = raw_data.drop_duplicates(subset=['question'])
# raw_data = raw_data.head(10000)
raw_queries = list(raw_data['question'])
# raw_queries = [q.strip() + '?' if not q.strip().endswith('?') else q.strip() for q in raw_data['question']]
# raw_queries = [q if not q.endswith('?') else q.strip('?') for q in raw_data['question']]
true_answers = list(raw_data['answers'])
ans_pids = [[item] for item in list(raw_data['anspid'])]
# print(supervised_method())
# print(unsupervised_method())
# print(iclfeed_method())
# print(colbert_method())
# print(dense_method())
print(sentence_colbert())