char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
2bb9bddaf
char/aliceai-t5-moe
1import pytest 2from utils import * 3 4# We use a F16 MOE gguf as main model, and q4_0 as draft model 5 6server = ServerPreset .stories15m_moe () 7 8MODEL_DRAFT_FILE_URL = "https://huggingface.co/ggml-org/tiny-llamas/resolve/main/stories15M-q4_0.gguf" 9 10def create_server (): 11global server 12server = ServerPreset .stories15m_moe () 13# set default values 14server .model_draft = download_file (MODEL_DRAFT_FILE_URL ) 15server .spec_type = "draft-simple" 16server .spec_draft_n_min = 4 17server .spec_draft_n_max = 8 18server .fa = "off" 19 20 21@ pytest . fixture ( autouse = True ) 22def fixture_create_server (): 23return create_server () 24 25 26def test_with_and_without_draft (): 27global server 28request = { 29"prompt" :"I believe the meaning of life is" , 30"temperature" :0.2 , 31"top_k" :5 , 32"seed" :4242 , 33"n_predict" :16 , 34"return_tokens" :True , 35 } 36 37server .model_draft = None # disable draft model 38server .spec_type = None 39server .start () 40res = server .make_request ("POST" ,"/completion" ,data = request ) 41assert res .status_code == 200 42tokens_no_draft = res .body ["tokens" ] 43server .stop () 44 45# create new server with draft model 46create_server () 47server .start () 48res = server .make_request ("POST" ,"/completion" ,data = request ) 49assert res .status_code == 200 50assert res .body ["timings" ]["draft_n" ]> 0 51tokens_draft = res .body ["tokens" ] 52 53assert tokens_no_draft == tokens_draft 54 55server .stop () 56create_server () 57assert server .spec_draft_n_max is not None 58server .spec_synth_rates = [0.0 ]* server .spec_draft_n_max 59server .start () 60res = server .make_request ("POST" ,"/completion" ,data = request ) 61 62assert res .status_code == 200 63assert res .body ["timings" ]["draft_n" ]> 0 64assert res .body ["timings" ]["draft_n_accepted" ]== 0 65assert res .body ["tokens" ]== tokens_no_draft 66 67 68def test_different_draft_min_draft_max (): 69global server 70test_values = [ 71 (1 ,2 ), 72 (1 ,4 ), 73 (4 ,8 ), 74 (4 ,12 ), 75 (8 ,16 ), 76 ] 77last_content = None 78for draft_min ,draft_max in test_values : 79server .stop () 80server .spec_draft_n_min = draft_min 81server .spec_draft_n_max = draft_max 82server .start () 83res = server .make_request ("POST" ,"/completion" ,data = { 84"prompt" :"I believe the meaning of life is" , 85"temperature" :0.0 , 86"top_k" :1 , 87"n_predict" :16 , 88 }) 89assert res .status_code == 200 90if last_content is not None : 91assert last_content == res .body ["content" ] 92last_content = res .body ["content" ] 93 94 95def test_synth_is_deterministic (): 96global server 97assert server .spec_draft_n_max is not None 98server .spec_synth_rates = [0.75 ** (i + 1 )for i in range (server .spec_draft_n_max )] 99server .start () 100 101request = { 102"prompt" :"I believe the meaning of life is" , 103"temperature" :0.2 , 104"top_k" :5 , 105"seed" :4242 , 106"n_predict" :32 , 107 } 108responses = [server .make_request ("POST" ,"/completion" ,data = request )for _ in range (2 )] 109 110for res in responses : 111assert res .status_code == 200 112assert res .body ["timings" ]["draft_n" ]> 0 113assert responses [0 ].body ["timings" ]["draft_n" ]== responses [1 ].body ["timings" ]["draft_n" ] 114assert responses [0 ].body ["timings" ]["draft_n_accepted" ]== responses [1 ].body ["timings" ]["draft_n_accepted" ] 115 116 117def test_synth_ignores_target_tokens (): 118global server 119assert server .spec_draft_n_max is not None 120server .spec_synth_rates = [1.0 ]* server .spec_draft_n_max 121server .start () 122 123res = server .make_request ("POST" ,"/completion" ,data = { 124"prompt" :"I believe the meaning of life is" , 125"temperature" :0.0 , 126"seed" :4242 , 127"n_predict" :32 , 128 }) 129 130assert res .status_code == 200 131assert res .body ["timings" ]["draft_n" ]> 0 132assert res .body ["timings" ]["draft_n_accepted" ]== res .body ["timings" ]["draft_n" ] 133 134res = server .make_request ("POST" ,"/completion" ,data = { 135"prompt" :"I believe the meaning of life is" , 136"temperature" :0.0 , 137"seed" :4242 , 138"n_predict" :6 , 139"grammar" :'root ::= "a"{5,5}' , 140 }) 141assert res .status_code == 200 ,res .body 142 143res = server .make_request ("POST" ,"/completion" ,data = { 144"prompt" :"Respond with only: OK" , 145"temperature" :0.0 , 146"seed" :4242 , 147"n_predict" :64 , 148"ignore_eos" :True , 149 }) 150assert res .status_code == 200 ,res .body 151assert res .body ["tokens_predicted" ]== 64 152assert res .body ["stop_type" ]== "limit" 153 154 155def test_slot_ctx_not_exceeded (): 156global server 157server .n_ctx = 256 158server .start () 159res = server .make_request ("POST" ,"/completion" ,data = { 160"prompt" :"Hello " * 248 , 161"temperature" :0.0 , 162"top_k" :1 , 163"speculative.p_min" :0.0 , 164 }) 165assert res .status_code == 200 166assert len (res .body ["content" ])> 0 167 168 169def test_with_ctx_shift (): 170global server 171server .n_ctx = 256 172server .enable_ctx_shift = True 173server .start () 174res = server .make_request ("POST" ,"/completion" ,data = { 175"prompt" :"Hello " * 248 , 176"temperature" :0.0 , 177"top_k" :1 , 178"n_predict" :256 , 179"speculative.p_min" :0.0 , 180 }) 181assert res .status_code == 200 182assert len (res .body ["content" ])> 0 183assert res .body ["tokens_predicted" ]== 256 184assert res .body ["truncated" ]== True 185 186 187@ pytest . mark . parametrize ( "n_slots,n_requests" , [ 188( 1 , 2 ), 189( 2 , 2 ), 190]) 191def test_multi_requests_parallel (n_slots :int ,n_requests :int ): 192global server 193server .n_slots = n_slots 194server .start () 195tasks = [] 196for _ in range (n_requests ): 197tasks .append ((server .make_request , ("POST" ,"/completion" , { 198"prompt" :"I believe the meaning of life is" , 199"temperature" :0.0 , 200"top_k" :1 , 201 }))) 202results = parallel_function_calls (tasks ) 203for res in results : 204assert res .status_code == 200 205assert match_regex ("(wise|kind|owl|answer)+" ,res .body ["content" ])