File size: 6,047 Bytes
28635a8
 
 
 
 
 
3f325ac
28635a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce15051
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import pandas as pd
from datasets import Dataset
from transformers import pipeline, GPT2Tokenizer
from sentence_transformers import SentenceTransformer, util

# Define paths and models
filename = "output_chess_details.txt"
retrieval_model_name = 'output/sentence-transformer-finetuned/'       #using a prefine-tuned model 
gpt2_model_name = "gpt2"
csv_file_path = "train_dataset.csv"
output_csv_file_path = "updated_train_dataset.csv"
val_csv_file_path = "val_dataset.csv"
output_val_csv_file_path = "updated_val_csv.csv"

tokenizer = GPT2Tokenizer.from_pretrained(gpt2_model_name)

# Initialize models
try:
    retrieval_model = SentenceTransformer(retrieval_model_name)
    gpt_model = pipeline("text-generation", model=gpt2_model_name)
    print("Models loaded successfully.")
except Exception as e:
    print(f"Failed to load models: {e}")

def load_and_preprocess_text(filename):
    """
    Load and preprocess text data from a file.
    Parameters:
    - filename (str): Path to the text file.
    Returns:
    - list[str]: A list of preprocessed text segments.
    """
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            segments = [line.strip() for line in file if line.strip()]
        print("Text loaded and preprocessed successfully.")
        return segments
    except Exception as e:
        print(f"Failed to load or preprocess text: {e}")
        return []

segments = load_and_preprocess_text(filename)

def find_relevant_segment(user_query, segments):
    """
    Find the most relevant text segment based on a user query.
    Parameters:
    - user_query (str): The user's query.
    - segments (list[str]): List of text segments to search within.
    Returns:
    - str: The most relevant text segment.
    """
    try:
        query_embedding = retrieval_model.encode(user_query)
        segment_embeddings = retrieval_model.encode(segments)
        similarities = util.pytorch_cos_sim(query_embedding, segment_embeddings)[0]
        best_idx = similarities.argmax()
        return segments[best_idx]
    except Exception as e:
        print(f"Error finding relevant segment: {e}")
        return ""

def generate_response(question):
    """
    Generate a response to a given question by finding a relevant text segment and
    using it to generate a more complete answer.
    Parameters:
    - question (str): The user's question.
    Returns:
    - str: Generated response.
    """
    relevant_segment = find_relevant_segment(question, segments)
    return generate_response_with_context(question, relevant_segment)

def generate_response_with_context(user_query, relevant_segment):
    """
    Generate a response based on a user query and a relevant segment.
    Parameters:
    - user_query (str): The user's query.
    - relevant_segment (str): A relevant fact or detail.
    Returns:
    - str: Formatted response incorporating the relevant segment.
    """
    try:
        prompt = f"Thank you for your question! Here is an additional fact about your topic: {relevant_segment}"
        max_tokens = len(tokenizer(prompt)['input_ids']) + 50
        response = gpt_model(prompt, max_length=max_tokens, temperature=0.25)[0]['generated_text']
        return clean_up_response(response, relevant_segment)
    except Exception as e:
        print(f"Error generating response: {e}")
        return ""

def clean_up_response(response, segment):
    """
    Clean up the generated response to ensure it is tidy and presentable.
    Parameters:
    - response (str): The initial response generated by the model.
    - segment (str): The segment used to generate the response.
    Returns:
    - str: A cleaned and formatted response.
    """
    sentences = response.split('.')
    cleaned_sentences = [sentence.strip() for sentence in sentences if sentence.strip() and sentence.strip() not in segment]
    cleaned_response = '. '.join(cleaned_sentences).strip()
    if cleaned_response and not cleaned_response.endswith((".", "!", "?")):
        cleaned_response += "."
    return cleaned_response

def process_dataset(csv_file_path, output_csv_file_path):
    """
    Process the dataset by generating responses and evaluating their similarities.
    Parameters:
    - csv_file_path (str): Path to the CSV file containing the dataset.
    - output_csv_file_path (str): Path where the updated dataset will be saved.
    Prints:
    - Path to the saved results and the average similarity score.
    """
    df = pd.read_csv(csv_file_path)
    dataset = Dataset.from_pandas(df)
    updated_dataset = add_model_answers(dataset)
    similarities = evaluate_similarity(updated_dataset)
    updated_dataset = updated_dataset.add_column("similarity", similarities)
    results_df = updated_dataset.to_pandas()
    results_df.to_csv(output_csv_file_path, index=False)
    average_similarity = sum(similarities) / len(similarities) if similarities else 0
    print(f"Results saved to {output_csv_file_path}")
    print(f"Average Similarity Score: {average_similarity:.3f}")

def add_model_answers(dataset):
    """
    Add generated answers to the dataset.
    Parameters:
    - dataset (datasets.Dataset): The Hugging Face dataset object.
    Returns:
    - datasets.Dataset: Updated dataset with added answers.
    """
    answers = [generate_response(q) for q in dataset['Question']]
    dataset = dataset.add_column("Answer", answers)
    return dataset

def evaluate_similarity(dataset):
    """
    Evaluate the similarity of generated answers against ground truth answers.
    Parameters:
    - dataset (datasets.Dataset): The dataset containing both answers and ground truths.
    Returns:
    - list[float]: List of similarity scores.
    """
    similarities = [util.pytorch_cos_sim(retrieval_model.encode(ans), retrieval_model.encode(gt))[0][0].item()
                    for ans, gt in zip(dataset['Answer'], dataset['GroundTruth'])]
    return similarities

# Process datasets
process_dataset(csv_file_path, output_csv_file_path)
process_dataset(val_csv_file_path, output_val_csv_file_path)