@@ -43,6 +43,27 @@ const (
4343	FailureTypeServerError     =  "server_error" 
4444	FailureTypeInvalidRequest  =  "invalid_request" 
4545	FailureTypeModelNotFound   =  "model_not_found" 
46+ 
47+ 	StopFinishReason          =  "stop" 
48+ 	LengthFinishReason        =  "length" 
49+ 	ToolsFinishReason         =  "tool_calls" 
50+ 	RemoteDecodeFinishReason  =  "remote_decode" 
51+ )
52+ 
53+ var  (
54+ 	requiredFinishReasons  =  []string {
55+ 		StopFinishReason ,
56+ 		LengthFinishReason ,
57+ 		ToolsFinishReason ,
58+ 		RemoteDecodeFinishReason ,
59+ 	}
60+ 
61+ 	validFinishReasons  =  map [string ]struct {}{
62+ 		StopFinishReason :         {},
63+ 		LengthFinishReason :       {},
64+ 		ToolsFinishReason :        {},
65+ 		RemoteDecodeFinishReason : {},
66+ 	}
4667)
4768
4869type  Configuration  struct  {
@@ -225,9 +246,9 @@ type Metrics struct {
225246	TPOTBucketValues  []int  `yaml:"tpot-buckets-values" json:"tpot-buckets-values"` 
226247	// RequestPromptTokens RequestGenerationTokens RequestParamsMaxTokens Histogram fake-observation arrays for init. 
227248	// Each value will be passed to Observe() once at start-up. 
228- 	RequestPromptTokens      []float64  `yaml:"request-prompt-tokens" json:"request-prompt-tokens"`          // prompt-length samples 
229- 	RequestGenerationTokens  []float64  `yaml:"request-generation-tokens" json:"request-generation-tokens"`  // generation-length samples 
230- 	RequestParamsMaxTokens   []float64  `yaml:"request-params-max-tokens" json:"request-params-max-tokens"`  // max_tokens parameter samples 
249+ 	RequestPromptTokens      []int  `yaml:"request-prompt-tokens" json:"request-prompt-tokens"`          // prompt-length samples 
250+ 	RequestGenerationTokens  []int  `yaml:"request-generation-tokens" json:"request-generation-tokens"`  // generation-length samples 
251+ 	RequestParamsMaxTokens   []int  `yaml:"request-params-max-tokens" json:"request-params-max-tokens"`  // max_tokens parameter samples 
231252	// RequestSuccessTotal is the number of successful requests, key: finish-reason (stop, length, etc.). 
232253	RequestSuccessTotal  map [string ]int64  `yaml:"request-success-total" json:"request-success-total"` 
233254}
@@ -508,16 +529,40 @@ func (c *Configuration) validate() error {
508529		if  c .FakeMetrics .KVCacheUsagePercentage  <  0  ||  c .FakeMetrics .KVCacheUsagePercentage  >  1  {
509530			return  errors .New ("fake metrics KV cache usage must be between 0 ans 1" )
510531		}
532+ 		if  c .FakeMetrics .TTFTBucketValues  !=  nil  {
533+ 			if  len (c .FakeMetrics .TTFTBucketValues ) >  len (TTFTBucketsBoundaries )+ 1  {
534+ 				return  errors .New ("fake time-to-first-token array is too long" )
535+ 			}
536+ 			for  v  :=  range  c .FakeMetrics .TTFTBucketValues  {
537+ 				if  v  <  0  {
538+ 					return  errors .New ("time-to-first-token fake metrics should contain only non-negative values" )
539+ 				}
540+ 			}
541+ 		}
542+ 		if  c .FakeMetrics .TPOTBucketValues  !=  nil  {
543+ 			if  len (c .FakeMetrics .TPOTBucketValues ) >  len (TPOTBucketsBoundaries )+ 1  {
544+ 				return  errors .New ("fake time-per-output-token array is too long" )
545+ 			}
546+ 			for  v  :=  range  c .FakeMetrics .TPOTBucketValues  {
547+ 				if  v  <  0  {
548+ 					return  errors .New ("time-per-output-token fake metrics should contain only non-negative values" )
549+ 				}
550+ 			}
551+ 		}
511552		if  c .FakeMetrics .RequestSuccessTotal  !=  nil  {
512553			for  reason , count  :=  range  c .FakeMetrics .RequestSuccessTotal  {
513554				if  count  <  0  {
514- 					return  fmt .Errorf ("fake metrics request-success-total.%s cannot be negative, got %d" , reason , count )
555+ 					return  fmt .Errorf ("fake metrics request-success-total.%s " + 
556+ 						"cannot be negative, got %d" , reason , count )
557+ 				}
558+ 				if  _ , ok  :=  validFinishReasons [reason ]; ! ok  {
559+ 					return  fmt .Errorf ("invalid finish reason in request-success-total: " + 
560+ 						"%s (valid reasons: %v)" , reason , requiredFinishReasons )
515561				}
516562			}
517- 			requiredReasons  :=  []string {StopFinishReason , LengthFinishReason , ToolsFinishReason , RemoteDecodeFinishReason }
518- 			for  _ , reason  :=  range  requiredReasons  {
563+ 			for  _ , reason  :=  range  requiredFinishReasons  {
519564				if  _ , exists  :=  c .FakeMetrics .RequestSuccessTotal [reason ]; ! exists  {
520- 					return   fmt . Errorf ( "missing required finish  reason in request-success-total: %s" ,  reason ) 
565+ 					c . FakeMetrics . RequestSuccessTotal [ reason ]  =   0 
521566				}
522567			}
523568		}
@@ -541,9 +586,27 @@ func (c *Configuration) validate() error {
541586	if  c .DPSize  <  1  ||  c .DPSize  >  8  {
542587		return  errors .New ("data parallel size must be between 1 ans 8" )
543588	}
589+ 
590+ 	if  (c .SSLCertFile  ==  "" ) !=  (c .SSLKeyFile  ==  "" ) {
591+ 		return  errors .New ("both ssl-certfile and ssl-keyfile must be provided together" )
592+ 	}
593+ 
594+ 	if  c .SelfSignedCerts  &&  (c .SSLCertFile  !=  ""  ||  c .SSLKeyFile  !=  "" ) {
595+ 		return  errors .New ("cannot use both self-signed-certs and explicit ssl-certfile/ssl-keyfile" )
596+ 	}
597+ 
598+ 	if  c .DatasetPath  ==  ""  &&  c .DatasetURL  !=  ""  {
599+ 		return  errors .New ("dataset-path is required when dataset-url is set" )
600+ 	}
601+ 
544602	return  nil 
545603}
546604
605+ // SSLEnabled returns true if SSL is enabled either via certificate files or self-signed certificates 
606+ func  (c  * Configuration ) SSLEnabled () bool  {
607+ 	return  (c .SSLCertFile  !=  ""  &&  c .SSLKeyFile  !=  "" ) ||  c .SelfSignedCerts 
608+ }
609+ 
547610func  (c  * Configuration ) Copy () (* Configuration , error ) {
548611	var  dst  Configuration 
549612	data , err  :=  json .Marshal (c )
@@ -628,6 +691,10 @@ func ParseCommandParamsAndLoadConfig() (*Configuration, error) {
628691	f .Var (& dummyFailureTypes , "failure-types" , failureTypesDescription )
629692	f .Lookup ("failure-types" ).NoOptDefVal  =  dummy 
630693
694+ 	f .StringVar (& config .SSLCertFile , "ssl-certfile" , config .SSLCertFile , "Path to SSL certificate file for HTTPS (optional)" )
695+ 	f .StringVar (& config .SSLKeyFile , "ssl-keyfile" , config .SSLKeyFile , "Path to SSL private key file for HTTPS (optional)" )
696+ 	f .BoolVar (& config .SelfSignedCerts , "self-signed-certs" , config .SelfSignedCerts , "Enable automatic generation of self-signed certificates for HTTPS" )
697+ 
631698	// These values were manually parsed above in getParamValueFromArgs, we leave this in order to get these flags in --help 
632699	var  dummyString  string 
633700	f .StringVar (& dummyString , "config" , "" , "The path to a yaml configuration file. The command line values overwrite the configuration file values" )
0 commit comments