add query generation

This commit is contained in:
hediehloo 2025-11-25 23:31:10 +00:00
parent 83ad2b88c0
commit c9ac8b436e
3 changed files with 246 additions and 7 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
.env
data
__pycache__

View File

@ -1,11 +1,86 @@
import json
import os
import requests
import tqdm
import faiss
import numpy
import importlib
from openai import OpenAI
from dotenv import load_dotenv
import re
import random
def import_lib(path, file_name, package_name):
file_path = path + "/" + file_name + ".py"
spec = importlib.util.spec_from_file_location(file_name, file_path)
imported_file = importlib.util.module_from_spec(spec)
spec.loader.exec_module(imported_file)
return getattr(imported_file, package_name)
OpenAIResponder = import_lib(os.path.dirname(__file__) , "openai_responder", "OpenAIResponder")
class Configuration:
def __init__(self):
pass
self.file_path = os.path.dirname(__file__)
self.session = requests.Session()
load_dotenv()
def get_config_prompt(self, passage, character, language):
config_prompt = f"""Given a **Passage** and **Character**, select the appropriate option from
def load_all_persona(self):
data = []
with open(self.file_path + "/../data/proj-persona/PersonaHub/persona.jsonl", "r", encoding="utf-8") as f:
for line in f:
data.append(json.loads(line))
all_persona = [data[i]["persona"] for i in range(len(data))]
return all_persona
def get_embedding(self, sentece, prompt_name):
embedding_url = "http://localhost:5011/embed"
headers = {"accept": "application/json"}
headers["Content-Type"] = "application/json"
data = {}
data["inputs"] = sentece
data["normalize"] = True
data["prompt_name"] = prompt_name
data["truncate"] = False
data["truncation_direction"] = "Right"
response = self.session.post(embedding_url, headers=headers, data=json.dumps(data), timeout=600)
return response.json()
def embedding_persona(self):
all_persona = self.load_all_persona()
prompt_name = "document"
all_embeddings = []
batch_size = 64
for i in tqdm.trange(0, len(all_persona), batch_size):
start_idx = i
stop_idx = min(len(all_persona), start_idx+batch_size)
all_embeddings += self.get_embedding(all_persona[start_idx:stop_idx], prompt_name)
xb = numpy.array(all_embeddings).astype('float32')
index = faiss.IndexFlatL2(len(all_embeddings[0]))
index.add(xb)
faiss.write_index(index, self.file_path + "/../data/faiss.index")
def get_config_prompt(self, passage, selected_persona, language):
character = "".join([f"- {selected_persona[i]}\n" for i in range(len(selected_persona))])
example1 = "{'passage': 'چیپست اسنپدراگون نام خانواده\\u200cای از SoCها یا «سیستم بر روی یک تراشه» است که توسط شرکت تراشه\\u200cساز آمریکایی کوالکام Qualcomm ساخته می شود. هدف از ساخت این تراشه\\u200cها استفاده از آنها در گوشی\\u200cهای همراه هوشمند و تبلت\\u200cهاست. هر تراشه\\u200cی اسنپ\\u200cدراگون شامل واحدهای پردازنده\\u200cی مرکزی، پردازنده\\u200cی گرافیکی Adreno، کنترلر دوربین، سیستم ناوبری جهانی GPS، مودم داخلی برای اتصال به شبکه\\u200cهای 5G و اتصال Wi-Fi است. در واقع در این تراشه\\u200cها تمام ابزارهای لازم برای توانمندسازی یک دستگاه هوشمند یکجا جمع شده است. البته تمام پردازنده های اسنپدراگون توانایی\\u200cهای برابری ندارد.', 'Character': 'A widely acclaimed microprocessor scientist passionate about creating next generation mobile chipsets', 'Question_Type': 'keywords', 'Difficulty': 'university'}"
example2 = '{\'passage\': \'امام علی(ع) پس از خلیفه سوم، به اصرار مسلمانان خلافت و حکومت را پذیرفت. او در دوران حکومتش اهمیت ویژه\\u200cای برای عدالت قائل بود و در برابر روش خلفا که بیت\\u200cالمال را بر اساس سوابق افراد تقسیم می\\u200cکردند، ایستاد. وی دستور داد که عرب و عجم و هر مسلمانی از هر تیره و تبار که باشد، در سهم بیت\\u200cالمال یکسان\\u200cاند و تمام زمین\\u200cهایی که عثمان به افراد مختلف واگذار کرده بود، به بیت\\u200cالمال بازگرداند. در دوره کوتاه حکومت امام علی(ع) سه جنگ سنگین داخلی جمل، صفین و نهروان درگرفت.\', \'Character\': "a devout Shi\'a Muslim scholar who has spent years studying Islamic scriptures and the life of Imam Ali.", \'Question_Type\': \'keywords\', \'Difficulty\': \'university\'}'
example3 = "{'passage': 'همه موجودات زنده بر اساس ویژگی های بسیار اساسی و مشترک طبقه بندی می شوند. سپس موجودات درون هر گروه به گروههای کوچکتر تقسیم می شوند. این گروه های کوچکتر بر اساس شباهت های دقیق تر در هر گروه بزرگتر هستند. این سیستم گروه بندی ، مطالعه گروه های خاصی از موجودات را برای دانشمندان آسان می کند. ویژگی هایی مانند ظاهر ، تولید مثل ، تحرک و عملکرد تنها چند روش برای گروه بندی موجودات زنده است. این گروه های تخصصی را طبقه بندی موجودات زنده می نامند. طبقه بندی موجودات زنده شامل ۷ سطح است: فرمانروا، شاخه، رده، راسته، خانواده، جنس و گونه', 'Character': 'a classification biologists who is slightly impatient with imprecise information.', 'Question_Type': 'acquire_knowledge', 'Difficulty': 'high_school'}"
config_prompt = f"""Given a **Passage** and **Character**, select the appropriate option from
three fields: Character, Question_Type, Difficulty, and return the output
in JSON format.
First, select the Character who are likely to be interested in the Passage
@ -25,15 +100,79 @@ Difficulty:
- university: ...
- phd: ...
Here are some examples
<Example1> <Example2> <Example3>
Example1: {example1}
Example2: {example2}
Example3: {example3}
Now, generate the **output** based on the **Passage** and **Character** from
user, the **Passage** will be in {language} language and the **Character**
will be in English.
,
,
Ensure to generate only the JSON output with content in English.
**Passage**:
{passage}
**Character**:
{character}"""
return config_prompt
return config_prompt
def init_persona(self):
self.index = faiss.read_index(self.file_path + "/../data/faiss.index")
self.all_persona = self.load_all_persona()
client = OpenAI(base_url=os.environ["OPENAI_BASE_URL"] ,api_key=os.environ["OPENAI_API_KEY"])
self.openai_responder = OpenAIResponder(client=client, model=os.environ["OPENAI_MODEL"], price_per_1m_input_tokens=0, price_per_1m_output_tokens=0)
def get_persona(self, passage):
query_embedding = self.get_embedding(passage, "query")
query = numpy.array(query_embedding, dtype='float32')
k = 5
distances, indices = self.index.search(query, k)
selected_persona = [self.all_persona[indices[0][i]] for i in range(len(indices[0]))]
return selected_persona
def get_messages(self, text):
messages = [
# {"role": "system", "content": ""},
{"role": "user", "content": text}
]
return messages
def run(self, passage):
selected_persona = self.get_persona(passage)
language = "persian"
prompt = self.get_config_prompt(passage, selected_persona, language)
messages = self.get_messages(prompt)
all_content, price = self.openai_responder.run(messages)
json_text = re.search(r"```json(.*?)```", all_content, re.DOTALL).group(1).strip()
config = json.loads(json_text)
# example = {"passage": passage}
# for key in data:
# example[key] = data[key]
config["length"] = random.choice([20, 40, 80, 160])
return config
if __name__ == "__main__":
configuration = Configuration()
# configuration.embedding_persona()
configuration.init_persona()
passage = """همه موجودات زنده بر اساس ویژگی های بسیار اساسی و مشترک طبقه بندی می شوند. سپس موجودات درون هر گروه به گروههای کوچکتر تقسیم می شوند. این گروه های کوچکتر بر اساس شباهت های دقیق تر در هر گروه بزرگتر هستند. این سیستم گروه بندی ، مطالعه گروه های خاصی از موجودات را برای دانشمندان آسان می کند. ویژگی هایی مانند ظاهر ، تولید مثل ، تحرک و عملکرد تنها چند روش برای گروه بندی موجودات زنده است. این گروه های تخصصی را طبقه بندی موجودات زنده می نامند. طبقه بندی موجودات زنده شامل ۷ سطح است: فرمانروا، شاخه، رده، راسته، خانواده، جنس و گونه"""
config = configuration.run(passage)

98
src/query_generator.py Normal file
View File

@ -0,0 +1,98 @@
import json
import os
import requests
import tqdm
import faiss
import numpy
import importlib
from openai import OpenAI
from dotenv import load_dotenv
import re
def import_lib(path, file_name, package_name):
file_path = path + "/" + file_name + ".py"
spec = importlib.util.spec_from_file_location(file_name, file_path)
imported_file = importlib.util.module_from_spec(spec)
spec.loader.exec_module(imported_file)
return getattr(imported_file, package_name)
OpenAIResponder = import_lib(os.path.dirname(__file__) , "openai_responder", "OpenAIResponder")
class QueryGenerator:
def __init__(self):
client = OpenAI(base_url=os.environ["OPENAI_BASE_URL"] ,api_key=os.environ["OPENAI_API_KEY"])
self.openai_responder = OpenAIResponder(client=client, model=os.environ["OPENAI_MODEL"], price_per_1m_input_tokens=0, price_per_1m_output_tokens=0)
def get_prompt(self, passage, character, corpus_language, queries_language, difficulty, length, language, question_type):
example = "{'passage': 'چیپست اسنپدراگون نام خانواده\\u200cای از SoCها یا «سیستم بر روی یک تراشه» است که توسط شرکت تراشه\\u200cساز آمریکایی کوالکام Qualcomm ساخته می شود. هدف از ساخت این تراشه\\u200cها استفاده از آنها در گوشی\\u200cهای همراه هوشمند و تبلت\\u200cهاست. هر تراشه\\u200cی اسنپ\\u200cدراگون شامل واحدهای پردازنده\\u200cی مرکزی، پردازنده\\u200cی گرافیکی Adreno، کنترلر دوربین، سیستم ناوبری جهانی GPS، مودم داخلی برای اتصال به شبکه\\u200cهای 5G و اتصال Wi-Fi است. در واقع در این تراشه\\u200cها تمام ابزارهای لازم برای توانمندسازی یک دستگاه هوشمند یکجا جمع شده است. البته تمام پردازنده های اسنپدراگون توانایی\\u200cهای برابری ندارد.', 'Character': 'A widely acclaimed microprocessor scientist passionate about creating next generation mobile chipsets', 'Question_Type': 'keywords', 'Difficulty': 'university'}"
example2 = '{\'passage\': \'امام علی(ع) پس از خلیفه سوم، به اصرار مسلمانان خلافت و حکومت را پذیرفت. او در دوران حکومتش اهمیت ویژه\\u200cای برای عدالت قائل بود و در برابر روش خلفا که بیت\\u200cالمال را بر اساس سوابق افراد تقسیم می\\u200cکردند، ایستاد. وی دستور داد که عرب و عجم و هر مسلمانی از هر تیره و تبار که باشد، در سهم بیت\\u200cالمال یکسان\\u200cاند و تمام زمین\\u200cهایی که عثمان به افراد مختلف واگذار کرده بود، به بیت\\u200cالمال بازگرداند. در دوره کوتاه حکومت امام علی(ع) سه جنگ سنگین داخلی جمل، صفین و نهروان درگرفت.\', \'Character\': "a devout Shi\'a Muslim scholar who has spent years studying Islamic scriptures and the life of Imam Ali.", \'Question_Type\': \'keywords\', \'Difficulty\': \'university\'}'
example3 = "{'passage': 'همه موجودات زنده بر اساس ویژگی های بسیار اساسی و مشترک طبقه بندی می شوند. سپس موجودات درون هر گروه به گروههای کوچکتر تقسیم می شوند. این گروه های کوچکتر بر اساس شباهت های دقیق تر در هر گروه بزرگتر هستند. این سیستم گروه بندی ، مطالعه گروه های خاصی از موجودات را برای دانشمندان آسان می کند. ویژگی هایی مانند ظاهر ، تولید مثل ، تحرک و عملکرد تنها چند روش برای گروه بندی موجودات زنده است. این گروه های تخصصی را طبقه بندی موجودات زنده می نامند. طبقه بندی موجودات زنده شامل ۷ سطح است: فرمانروا، شاخه، رده، راسته، خانواده، جنس و گونه', 'Character': 'a classification biologists who is slightly impatient with imprecise information.', 'Question_Type': 'acquire_knowledge', 'Difficulty': 'high_school'}"
prompt = f"""Given a **Character**, **Passage**, and **Requirement**, generate a query from the **Character**'s perspective that satisfies the **Requirement** and can be used to retrieve the **Passage**. Please return the result in JSON format.
Here is an example:
<example>
Now, generate the **output** based on the **Character**, **Passage** and **Requirement** from user, the **Passage** will be in {corpus_language} language, the **Character** and **Requirement** will be in English.
Ensure to generate only the JSON output, with the key in English and the value, in {queries_language} language.
**Character**
{character}
**Passage**
{passage}
**Requirment**
- Question_Type: {question_type};
- Difficulty: {difficulty};
- Length: the length of the generated sentences should be {length} words;
- Languange: the language in which the results are generated should be, {language} language;"""
return prompt
def get_messages(self, text):
messages = [
# {"role": "system", "content": ""},
{"role": "user", "content": text}
]
return messages
def run(self, passage, config):
language = "persian"
corpus_language = "persian"
queries_language = "persian"
prompt = self.get_prompt(passage, config["Character"], corpus_language, queries_language, config["Difficulty"], config["length"], language, config["Question_Type"])
messages = self.get_messages(prompt)
all_content, price = self.openai_responder.run(messages)
json_text = re.search(r"```json(.*?)```", all_content, re.DOTALL).group(1).strip()
data = json.loads(json_text)
# example = {"passage": passage}
# for key in data:
# example[key] = data[key]
return data
def main():
configuration = Configuration()
configuration.init_persona()
passage = """همه موجودات زنده بر اساس ویژگی های بسیار اساسی و مشترک طبقه بندی می شوند. سپس موجودات درون هر گروه به گروههای کوچکتر تقسیم می شوند. این گروه های کوچکتر بر اساس شباهت های دقیق تر در هر گروه بزرگتر هستند. این سیستم گروه بندی ، مطالعه گروه های خاصی از موجودات را برای دانشمندان آسان می کند. ویژگی هایی مانند ظاهر ، تولید مثل ، تحرک و عملکرد تنها چند روش برای گروه بندی موجودات زنده است. این گروه های تخصصی را طبقه بندی موجودات زنده می نامند. طبقه بندی موجودات زنده شامل ۷ سطح است: فرمانروا، شاخه، رده، راسته، خانواده، جنس و گونه"""
config = configuration.run(passage)
query_generator = QueryGenerator()
data = query_generator.run(passage, config)
if __name__ == "__main__":
Configuration = import_lib(os.path.dirname(__file__) , "configuration", "Configuration")
main()