readCtrl_lambda / code /classifier /few_shot_testing_v2.py
mshahidul
Initial commit of readCtrl code without large models
030876e
Raw
History Blame Contribute Delete
4.32 kB
import json
import requests
import random
import os
import csv
import numpy as np
# --- Configuration ---
DEV_SET_PATH = "/home/mshahidul/readctrl/data/new_exp/test_health_literacy_data.json"
FEW_SHOT_POOL_PATH = "/home/mshahidul/readctrl/data/new_exp/final_prompt_template_info.json"
LOCAL_API_URL = "http://172.16.34.29:8004/v1/chat/completions"
LOCAL_MODEL_NAME = "Qwen/Qwen3-30B-A3B-Instruct-2507"
# EXPERIMENT SETTINGS
SHOTS_TO_EVALUATE = [1, 2, 3,4,5,6]
NUM_TRIALS = 3 # How many times to run each shot-count with different random samples
# --- Logic ---
def build_random_prompt(few_shot_data, k_per_label):
"""Randomly samples k examples per label and builds a prompt."""
instruction = (
"You are an expert in health communication. Your task is to judge the health literacy level of the provided text.\n"
"Classify the text into: low_health_literacy, intermediate_health_literacy, or proficient_health_literacy.\n\n"
)
# Organize pool by label
categorized = {}
for entry in few_shot_data:
label = entry['label']
categorized.setdefault(label, []).append(entry)
few_shot_blocks = "### Examples:\n"
labels = ["low_health_literacy", "intermediate_health_literacy", "proficient_health_literacy"]
for label in labels:
# RANDOM SAMPLING: Shuffle and take k
pool = categorized.get(label, [])
selected = random.sample(pool, min(k_per_label, len(pool)))
for ex in selected:
few_shot_blocks += f"Target Text: \"{ex['gen_text']}\"\n"
few_shot_blocks += f"Reasoning: {ex['reasoning']}\n"
few_shot_blocks += f"Label: {label}\n"
few_shot_blocks += "-" * 30 + "\n"
return instruction + few_shot_blocks + "\n### Task:\nTarget Text: \"{input_text}\"\nReasoning:"
def get_prediction(prompt_template, input_text):
final_prompt = prompt_template.format(input_text=input_text)
payload = {"model": LOCAL_MODEL_NAME, "messages": [{"role": "user", "content": final_prompt}], "temperature": 0}
try:
response = requests.post(LOCAL_API_URL, json=payload, timeout=30)
return response.json()['choices'][0]['message']['content'].strip()
except: return "Error"
def parse_label(text):
text = text.lower()
if "low" in text: return "low_health_literacy"
if "intermediate" in text: return "intermediate_health_literacy"
if "proficient" in text: return "proficient_health_literacy"
return "unknown"
# --- Execution ---
with open(DEV_SET_PATH, 'r') as f:
dev_set = json.load(f)
with open(FEW_SHOT_POOL_PATH, 'r') as f:
few_shot_pool = json.load(f)
# Ensure no data leakage (remove few-shot examples from dev set)
shot_ids = {item['doc_id'] for item in few_shot_pool}
clean_dev_set = [item for item in dev_set if item['doc_id'] not in shot_ids]
final_summary = []
for k in SHOTS_TO_EVALUATE:
trial_accuracies = []
print(f"\n>>> Starting evaluation for {k}-shot ({NUM_TRIALS} trials)")
for t in range(NUM_TRIALS):
# Create a prompt with a NEW random sample for this trial
current_template = build_random_prompt(few_shot_pool, k)
correct = 0
for case in clean_dev_set:
pred = parse_label(get_prediction(current_template, case['gen_text']))
if pred == parse_label(case['label']):
correct += 1
acc = (correct / len(clean_dev_set)) * 100
trial_accuracies.append(acc)
print(f" Trial {t+1}/{NUM_TRIALS}: Accuracy = {acc:.2f}%")
# Calculate statistics for the shot count
avg_acc = np.mean(trial_accuracies)
std_dev = np.std(trial_accuracies)
final_summary.append({
"shots_per_label": k,
"average_accuracy": round(avg_acc, 2),
"std_dev": round(std_dev, 2),
"trial_results": trial_accuracies
})
# --- Save Results ---
output_json = "/home/mshahidul/readctrl/data/new_exp/random_trial_results.json"
with open(output_json, 'w') as f:
json.dump(final_summary, f, indent=4)
print("\n" + "="*40)
print(f"{'Shots':<10} | {'Avg Accuracy':<15} | {'Std Dev':<10}")
print("-" * 40)
for res in final_summary:
print(f"{res['shots_per_label']:<10} | {res['average_accuracy']:<15}% | {res['std_dev']:<10}")
print("="*40)