Lily-Trinh commited on
Commit
cb09868
·
verified ·
1 Parent(s): 42a7d03

Upload predict.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. predict.py +164 -0
predict.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import csv
3
+ import json
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ from deployment import load_bundle, load_networks, predict_text
8
+
9
+
10
+ def read_records(path, text_column):
11
+ suffix = path.suffix.lower()
12
+
13
+ if suffix == ".txt":
14
+ records = []
15
+ with path.open(encoding="utf-8") as input_file:
16
+ for line_number, line in enumerate(input_file, start=1):
17
+ text = line.strip()
18
+ if text:
19
+ records.append({"id": line_number, text_column: text})
20
+ return records
21
+
22
+ if suffix == ".csv":
23
+ with path.open(encoding="utf-8-sig", newline="") as input_file:
24
+ records = list(csv.DictReader(input_file))
25
+ if records and text_column not in records[0]:
26
+ raise ValueError(
27
+ f"CSV does not contain a '{text_column}' column. "
28
+ f"Available columns: {list(records[0])}"
29
+ )
30
+ return records
31
+
32
+ if suffix in {".jsonl", ".ndjson"}:
33
+ records = []
34
+ with path.open(encoding="utf-8") as input_file:
35
+ for line_number, line in enumerate(input_file, start=1):
36
+ if not line.strip():
37
+ continue
38
+ record = json.loads(line)
39
+ if not isinstance(record, dict):
40
+ raise ValueError(
41
+ f"JSONL line {line_number} must contain an object."
42
+ )
43
+ if text_column not in record:
44
+ raise ValueError(
45
+ f"JSONL line {line_number} does not contain "
46
+ f"'{text_column}'."
47
+ )
48
+ records.append(record)
49
+ return records
50
+
51
+ raise ValueError("Input file must be .txt, .csv, .jsonl, or .ndjson.")
52
+
53
+
54
+ def add_predictions(record, predictions):
55
+ result = dict(record)
56
+ for dimension, values in predictions.items():
57
+ result[f"{dimension}_probability"] = values["probability"]
58
+ result[f"{dimension}_prediction"] = values["prediction"]
59
+ return result
60
+
61
+
62
+ def write_records(path, records):
63
+ path.parent.mkdir(parents=True, exist_ok=True)
64
+ suffix = path.suffix.lower()
65
+
66
+ if suffix == ".csv":
67
+ if not records:
68
+ path.write_text("", encoding="utf-8")
69
+ return
70
+ with path.open("w", encoding="utf-8", newline="") as output_file:
71
+ writer = csv.DictWriter(output_file, fieldnames=list(records[0]))
72
+ writer.writeheader()
73
+ writer.writerows(records)
74
+ return
75
+
76
+ if suffix in {".jsonl", ".ndjson"}:
77
+ with path.open("w", encoding="utf-8") as output_file:
78
+ for record in records:
79
+ output_file.write(json.dumps(record) + "\n")
80
+ return
81
+
82
+ if suffix == ".json":
83
+ path.write_text(json.dumps(records, indent=2), encoding="utf-8")
84
+ return
85
+
86
+ raise ValueError("Output file must be .csv, .json, .jsonl, or .ndjson.")
87
+
88
+
89
+ def main():
90
+ parser = argparse.ArgumentParser(
91
+ description="Predict personality dimensions from new text."
92
+ )
93
+ parser.add_argument("bundle", help="Path to a saved .pt model bundle.")
94
+ parser.add_argument(
95
+ "--text",
96
+ help="A single text to classify.",
97
+ )
98
+ parser.add_argument(
99
+ "--input",
100
+ type=Path,
101
+ help="Batch input file: .txt, .csv, .jsonl, or .ndjson.",
102
+ )
103
+ parser.add_argument(
104
+ "--output",
105
+ type=Path,
106
+ help="Batch output file: .csv, .json, .jsonl, or .ndjson.",
107
+ )
108
+ parser.add_argument(
109
+ "--text-column",
110
+ default="text",
111
+ help="Text field for CSV/JSONL input (default: text).",
112
+ )
113
+ args = parser.parse_args()
114
+
115
+ bundle = load_bundle(args.bundle)
116
+ networks = load_networks(bundle)
117
+
118
+ if args.input:
119
+ if args.text is not None:
120
+ parser.error("--text and --input cannot be used together")
121
+ if not args.output:
122
+ parser.error("--output is required with --input")
123
+ if not args.input.is_file():
124
+ parser.error(f"input file does not exist: {args.input}")
125
+
126
+ try:
127
+ records = read_records(args.input, args.text_column)
128
+ results = []
129
+ for row_number, record in enumerate(records, start=1):
130
+ text = record.get(args.text_column)
131
+ if not isinstance(text, str) or not text.strip():
132
+ raise ValueError(
133
+ f"Row {row_number} has an empty or invalid "
134
+ f"'{args.text_column}' value."
135
+ )
136
+ results.append(
137
+ add_predictions(
138
+ record,
139
+ predict_text(text, bundle, networks=networks),
140
+ )
141
+ )
142
+ write_records(args.output, results)
143
+ except (OSError, ValueError, json.JSONDecodeError) as error:
144
+ parser.error(str(error))
145
+
146
+ print(f"Wrote {len(results)} prediction(s) to {args.output}")
147
+ return
148
+
149
+ if args.output:
150
+ parser.error("--output can only be used with --input")
151
+
152
+ text = args.text if args.text is not None else sys.stdin.read()
153
+ if not text.strip():
154
+ parser.error("prediction text cannot be empty")
155
+
156
+ result = {
157
+ "dataset": bundle["dataset"],
158
+ "predictions": predict_text(text, bundle, networks=networks),
159
+ }
160
+ print(json.dumps(result, indent=2))
161
+
162
+
163
+ if __name__ == "__main__":
164
+ main()