bench_other.py 5.35 KB
Newer Older
Lianmin Zheng's avatar
Lianmin Zheng committed
1
2
3
import argparse
import json
import time
Liangsheng Yin's avatar
Liangsheng Yin committed
4
5
from concurrent.futures import ThreadPoolExecutor
from functools import partial
Lianmin Zheng's avatar
Lianmin Zheng committed
6
7
8

from tqdm import tqdm

Liangsheng Yin's avatar
Liangsheng Yin committed
9
10
11
12
13
from sglang.test.test_utils import (
    add_common_other_args_and_parse,
    call_generate_lightllm,
    call_generate_srt_raw,
    call_generate_vllm,
Lianmin Zheng's avatar
Lianmin Zheng committed
14
)
Liangsheng Yin's avatar
Liangsheng Yin committed
15
16
17
from sglang.utils import dump_state_text, read_jsonl

system_prompt = "Please serve as an impartial judge and rigorously evaluate the quality of the following article. Apply the most stringent standards possible, showing no leniency."
Lianmin Zheng's avatar
Lianmin Zheng committed
18
19

dimension_prompts = [
Liangsheng Yin's avatar
Liangsheng Yin committed
20
21
22
23
24
25
    "Content: This refers to the essences of the essay. The substance should be well researched, accurate, relevant to the topic and should show a thorough understanding of the subject. The essay should also reflect a clear goal or purpose.",
    "Organization and Structure: An essay needs to be properly structured with a clear introduction, body, and conclusion. The essay should flow naturally, with one paragraph leading seamlessly into the next.",
    "Argument and Analysis: The argument made in the essay should be logical, coherent and clearly articulated. Each point made should be backed up by solid evidence and thorough analysis.",
    "Clarity and Precision: The essay should be written in a clear and concise manner. The points made should be easily understood by the reader. The language used should also be precise and unambiguous.",
    "Grammar and Punctuation: Proper use of grammar and punctuation is vital in an academic essay. Errors in grammar and punctuation not only distract the reader but can also negatively impact the meaning and interpretation of the content.",
    "Referencing and Citation: An essay should contain proper citations and references for all sources used. This not only prevents accusations of plagiarism but also gives credit to the authors of the works that have contributed to the essay. The citation should adhere to a specific format as required by the academic institution or specified by the professor.",
Lianmin Zheng's avatar
Lianmin Zheng committed
26
27
28
29
30
31
32
33
34
]


def multi_dimension_judge(article, generate):
    s = system_prompt
    s += "\n```\n" + article + "\n```\n\n"

    judges = []
    for i in range(len(dimension_prompts)):
Liangsheng Yin's avatar
Liangsheng Yin committed
35
36
37
38
39
40
41
42
43
44
        comp = generate(
            s
            + "USER: Please judge the quality based on the following metric. "
            + dimension_prompts[i]
            + " Please provide a single-paragraph judgement. "
            + "Focus on the provided metric and do not say other things. "
            'End your judgement paragraph with the word "END"\nJUDGE:',
            max_tokens=256,
            stop="END",
        )
Lianmin Zheng's avatar
Lianmin Zheng committed
45
46
47
48
49
50
51
52
53
54
55
56
57
        judges.append(comp)

    s += "I will judge the quality based on the following metrics.\n"
    for i in range(len(dimension_prompts)):
        s += dimension_prompts[i].split(":")[0] + ": " + judges[i].strip() + "\n"

    s += "In summary, on a scale of 1 to 10, I would give the article a score of"
    s += generate(s, max_tokens=2, stop=None)

    return s


def main(args):
Liangsheng Yin's avatar
Liangsheng Yin committed
58
    lines = read_jsonl(args.data_path)[: args.num_questions]
Lianmin Zheng's avatar
Lianmin Zheng committed
59
60
61
62
63
64
65
66
67
68
69
70
71
    states = [None] * len(lines)

    # Select backend
    if args.backend == "lightllm":
        url = f"{args.host}:{args.port}/generate"
        generate = partial(call_generate_lightllm, url=url, temperature=0)
    elif args.backend == "vllm":
        url = f"{args.host}:{args.port}/generate"
        generate = partial(call_generate_vllm, url=url, temperature=0)
    elif args.backend == "srt-raw":
        url = f"{args.host}:{args.port}/generate"
        generate = partial(call_generate_srt_raw, url=url, temperature=0)
    elif args.backend == "guidance":
Liangsheng Yin's avatar
Liangsheng Yin committed
72
        from guidance import gen, models
Lianmin Zheng's avatar
Lianmin Zheng committed
73

Liangsheng Yin's avatar
Liangsheng Yin committed
74
75
76
77
78
        model = models.LlamaCpp(
            "/home/ubuntu/model_weights/Llama-2-7b-chat.gguf",
            n_gpu_layers=-1,
            n_ctx=4096,
        )
Lianmin Zheng's avatar
Lianmin Zheng committed
79
80

        def generate(prompt, max_tokens, stop):
Liangsheng Yin's avatar
Liangsheng Yin committed
81
82
83
84
85
            out = (
                model
                + prompt
                + gen(name="answer", max_tokens=max_tokens, temperature=0, stop=stop)
            )
Lianmin Zheng's avatar
Lianmin Zheng committed
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
            return out["answer"]

        # warmup
        generate("Hello!", max_tokens=8, stop=None)
    else:
        raise ValueError(f"Invalid backend: {args.backend}")

    # Run requests
    def get_one_answer(i):
        states[i] = multi_dimension_judge(lines[i], generate)

    tic = time.time()
    if args.parallel == 1:
        for i in tqdm(range(len(lines))):
            get_one_answer(i)
    else:
        with ThreadPoolExecutor(args.parallel) as executor:
            executor.map(get_one_answer, list(range(len(lines))))
    latency = time.time() - tic

    # Compute accuracy
    print(f"Latency: {latency:.3f}")

    # Write results
    dump_state_text(f"tmp_output_{args.backend}.txt", states)

    with open(args.result_file, "a") as fout:
        value = {
            "task": "llm_judge",
            "backend": args.backend,
            "num_gpus": 1,
            "latency": round(latency, 3),
            "num_requests": args.num_questions,
            "other": {
                "num_questions": args.num_questions,
                "parallel": args.parallel,
Liangsheng Yin's avatar
Liangsheng Yin committed
122
            },
Lianmin Zheng's avatar
Lianmin Zheng committed
123
124
125
126
127
128
129
130
131
132
        }
        fout.write(json.dumps(value) + "\n")


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--data-path", type=str, default="articles.jsonl")
    parser.add_argument("--num-questions", type=int, default=20)
    args = add_common_other_args_and_parse(parser)
    main(args)