mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-10-31 08:51:55 +00:00 
			
		
		
		
	Server: format error to json (#5961)
* server: format error to json * server: do not crash on grammar error * fix api key test case * revert limit max n_predict * small fix * correct coding style * update completion.js * launch_slot_with_task * update docs * update_slots * update webui * update readme
This commit is contained in:
		| @@ -556,9 +556,51 @@ Run with bash: | |||||||
| bash chat.sh | bash chat.sh | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### API like OAI | ### OAI-like API | ||||||
|  |  | ||||||
| The HTTP server supports OAI-like API | The HTTP server supports OAI-like API: https://github.com/openai/openai-openapi | ||||||
|  |  | ||||||
|  | ### API errors | ||||||
|  |  | ||||||
|  | Server returns error in the same format as OAI: https://github.com/openai/openai-openapi | ||||||
|  |  | ||||||
|  | Example of an error: | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |     "error": { | ||||||
|  |         "code": 401, | ||||||
|  |         "message": "Invalid API Key", | ||||||
|  |         "type": "authentication_error" | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Apart from error types supported by OAI, we also have custom types that are specific to functionalities of llama.cpp: | ||||||
|  |  | ||||||
|  | **When /metrics or /slots endpoint is disabled** | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |     "error": { | ||||||
|  |         "code": 501, | ||||||
|  |         "message": "This server does not support metrics endpoint.", | ||||||
|  |         "type": "not_supported_error" | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | **When the server receives invalid grammar via */completions endpoint** | ||||||
|  |  | ||||||
|  | ```json | ||||||
|  | { | ||||||
|  |     "error": { | ||||||
|  |         "code": 400, | ||||||
|  |         "message": "Failed to parse grammar", | ||||||
|  |         "type": "invalid_request_error" | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ### Extending or building alternative Web Front End | ### Extending or building alternative Web Front End | ||||||
|  |  | ||||||
|   | |||||||
| @@ -231,255 +231,256 @@ unsigned char completion_js[] = { | |||||||
|   0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, |   0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, | ||||||
|   0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, |   0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, | ||||||
|   0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, |   0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, | ||||||
|   0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, |   0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x4a, 0x53, 0x4f, | ||||||
|   0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x4e, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x28, 0x72, 0x65, 0x73, 0x75, | ||||||
|   0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, |   0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20, | ||||||
|   0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, |   0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, | ||||||
|   0x28, 0x27, 0x73, 0x6c, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, |   0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, | ||||||
|   0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x27, 0x29, 0x29, 0x20, 0x7b, 0x0a, |   0x65, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x28, 0x27, | ||||||
|  |   0x73, 0x6c, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, | ||||||
|  |   0x61, 0x62, 0x6c, 0x65, 0x27, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x61, |   0x20, 0x20, 0x2f, 0x2f, 0x20, 0x54, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x61, | ||||||
|   0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x62, |   0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x62, | ||||||
|   0x65, 0x20, 0x63, 0x61, 0x75, 0x67, 0x68, 0x74, 0x20, 0x62, 0x79, 0x20, |   0x65, 0x20, 0x63, 0x61, 0x75, 0x67, 0x68, 0x74, 0x20, 0x62, 0x79, 0x20, | ||||||
|   0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6c, |   0x75, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6c, | ||||||
|   0x6c, 0x65, 0x72, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x6c, 0x65, 0x72, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x72, | ||||||
|   0x20, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x27, |   0x6f, 0x77, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, | ||||||
|   0x73, 0x6c, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, |   0x28, 0x27, 0x73, 0x6c, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, | ||||||
|   0x61, 0x62, 0x6c, 0x65, 0x27, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x27, 0x29, 0x3b, 0x0a, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x60, 0x6c, 0x6c, |   0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, | ||||||
|   0x61, 0x6d, 0x61, 0x2e, 0x63, 0x70, 0x70, 0x20, 0x65, 0x72, 0x72, 0x6f, |   0x6f, 0x72, 0x28, 0x60, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x2e, 0x63, 0x70, | ||||||
|   0x72, 0x3a, 0x20, 0x24, 0x7b, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, |   0x70, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x5b, 0x24, 0x7b, 0x72, | ||||||
|   0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, |   0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, | ||||||
|   0x74, 0x7d, 0x60, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x63, 0x6f, 0x64, 0x65, 0x7d, 0x20, 0x2d, 0x20, 0x24, 0x7b, 0x72, 0x65, | ||||||
|  |   0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x74, | ||||||
|  |   0x79, 0x70, 0x65, 0x7d, 0x5d, 0x3a, 0x20, 0x24, 0x7b, 0x72, 0x65, 0x73, | ||||||
|  |   0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x6d, 0x65, | ||||||
|  |   0x73, 0x73, 0x61, 0x67, 0x65, 0x7d, 0x60, 0x29, 0x3b, 0x0a, 0x20, 0x20, | ||||||
|  |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|  |   0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|  |   0x20, 0x20, 0x7d, 0x20, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x29, | ||||||
|  |   0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|  |   0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, | ||||||
|  |   0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x60, 0x6c, 0x6c, 0x61, 0x6d, | ||||||
|  |   0x61, 0x2e, 0x63, 0x70, 0x70, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, | ||||||
|  |   0x24, 0x7b, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, | ||||||
|  |   0x6f, 0x72, 0x7d, 0x60, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, |  | ||||||
|   0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, |  | ||||||
|   0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |  | ||||||
|   0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, 0x72, 0x72, |  | ||||||
|   0x6f, 0x72, 0x20, 0x3d, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61, |  | ||||||
|   0x72, 0x73, 0x65, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x65, |  | ||||||
|   0x72, 0x72, 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, |  | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, |  | ||||||
|   0x6c, 0x65, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x60, 0x6c, 0x6c, |  | ||||||
|   0x61, 0x6d, 0x61, 0x2e, 0x63, 0x70, 0x70, 0x20, 0x65, 0x72, 0x72, 0x6f, |  | ||||||
|   0x72, 0x3a, 0x20, 0x24, 0x7b, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, |  | ||||||
|   0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, |  | ||||||
|   0x74, 0x7d, 0x60, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |  | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, |   0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x20, 0x63, 0x61, |   0x63, 0x61, 0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x29, 0x20, 0x7b, 0x0a, | ||||||
|   0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x65, 0x2e, 0x6e, 0x61, | ||||||
|   0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, |   0x6d, 0x65, 0x20, 0x21, 0x3d, 0x3d, 0x20, 0x27, 0x41, 0x62, 0x6f, 0x72, | ||||||
|   0x20, 0x21, 0x3d, 0x3d, 0x20, 0x27, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x45, |   0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x27, 0x29, 0x20, 0x7b, 0x0a, 0x20, | ||||||
|   0x72, 0x72, 0x6f, 0x72, 0x27, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, | ||||||
|   0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, |   0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x6c, 0x6c, 0x61, 0x6d, | ||||||
|   0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x20, |   0x61, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x22, 0x2c, 0x20, | ||||||
|   0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x22, 0x2c, 0x20, 0x65, 0x29, |   0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, | ||||||
|   0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x65, 0x3b, 0x0a, 0x20, | ||||||
|   0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x7d, |   0x20, 0x7d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, | ||||||
|   0x0a, 0x20, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x7b, |   0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, | ||||||
|   0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, |   0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x28, | ||||||
|   0x6c, 0x65, 0x72, 0x2e, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x28, 0x29, 0x3b, |   0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x72, 0x65, | ||||||
|   0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, |   0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, | ||||||
|   0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3b, 0x0a, |   0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x2f, 0x2f, 0x20, 0x43, 0x61, 0x6c, 0x6c, | ||||||
|   0x7d, 0x0a, 0x0a, 0x2f, 0x2f, 0x20, 0x43, 0x61, 0x6c, 0x6c, 0x20, 0x6c, |   0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, | ||||||
|   0x6c, 0x61, 0x6d, 0x61, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, |   0x72, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, | ||||||
|   0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x61, |   0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, | ||||||
|   0x72, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, |   0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x73, 0x75, 0x62, 0x73, | ||||||
|   0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, |   0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x0a, 0x2f, 0x2f, 0x0a, | ||||||
|   0x69, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x0a, 0x2f, 0x2f, 0x0a, 0x2f, 0x2f, |   0x2f, 0x2f, 0x20, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0a, | ||||||
|   0x20, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0a, 0x2f, 0x2f, |   0x2f, 0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, | ||||||
|   0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, |   0x6f, 0x72, 0x74, 0x20, 0x7b, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x45, | ||||||
|   0x74, 0x20, 0x7b, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x45, 0x76, 0x65, |   0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x7d, | ||||||
|   0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x7d, 0x20, 0x66, |   0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x27, 0x2f, 0x63, 0x6f, 0x6d, 0x70, | ||||||
|   0x72, 0x6f, 0x6d, 0x20, 0x27, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, |   0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6a, 0x73, 0x27, 0x0a, 0x2f, | ||||||
|   0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6a, 0x73, 0x27, 0x0a, 0x2f, 0x2f, 0x0a, |   0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, | ||||||
|   0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, |   0x74, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x20, 0x3d, 0x20, 0x6c, 0x6c, 0x61, | ||||||
|   0x63, 0x6f, 0x6e, 0x6e, 0x20, 0x3d, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, |   0x6d, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, | ||||||
|   0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x28, |   0x74, 0x28, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x29, 0x0a, 0x2f, 0x2f, | ||||||
|   0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x29, 0x0a, 0x2f, 0x2f, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x2e, 0x61, 0x64, 0x64, | ||||||
|   0x20, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x2e, 0x61, 0x64, 0x64, 0x45, 0x76, |   0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, | ||||||
|   0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x28, |   0x72, 0x28, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, | ||||||
|   0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x20, 0x28, |   0x20, 0x28, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x29, 0x20, 0x3d, 0x3e, 0x20, | ||||||
|   0x63, 0x68, 0x75, 0x6e, 0x6b, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, |   0x7b, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, | ||||||
|   0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, |   0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, | ||||||
|   0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x63, |   0x28, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x65, 0x74, 0x61, 0x69, | ||||||
|   0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x2e, |   0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x2f, | ||||||
|   0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x2f, 0x2f, 0x20, |   0x2f, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, 0x2f, 0x2f, 0x0a, 0x65, | ||||||
|   0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, 0x2f, 0x2f, 0x0a, 0x65, 0x78, 0x70, |   0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, | ||||||
|   0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x6c, |   0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, | ||||||
|   0x61, 0x6d, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, |   0x72, 0x67, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x6d, | ||||||
|   0x65, 0x74, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, |   0x70, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x3d, | ||||||
|   0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x3d, 0x20, 0x7b, |   0x20, 0x7b, 0x7d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, | ||||||
|   0x7d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x3d, 0x20, |   0x3d, 0x20, 0x7b, 0x7d, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, | ||||||
|   0x7b, 0x7d, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x63, |   0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, | ||||||
|   0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, |   0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, | ||||||
|   0x72, 0x67, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x45, |   0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, | ||||||
|   0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x28, 0x29, |   0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, | ||||||
|   0x3b, 0x0a, 0x20, 0x20, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x28, |   0x20, 0x28, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, | ||||||
|   0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, |   0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, | ||||||
|   0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, |   0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, | ||||||
|   0x20, 0x22, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, |   0x6f, 0x72, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x28, 0x63, 0x6f, | ||||||
|   0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x28, 0x63, 0x6f, 0x6e, 0x73, |   0x6e, 0x73, 0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x6f, 0x66, | ||||||
|   0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x6c, |   0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x28, 0x70, 0x72, 0x6f, 0x6d, 0x70, | ||||||
|   0x6c, 0x61, 0x6d, 0x61, 0x28, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x2c, |   0x74, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, | ||||||
|   0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, |   0x6f, 0x6e, 0x66, 0x69, 0x67, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, | ||||||
|   0x66, 0x69, 0x67, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x68, 0x75, 0x6e, | ||||||
|   0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, |   0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, | ||||||
|   0x64, 0x61, 0x74, 0x61, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, |   0x74, 0x20, 0x2b, 0x3d, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, | ||||||
|   0x2b, 0x3d, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, |   0x61, 0x74, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3b, | ||||||
|   0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x20, |   0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x65, | ||||||
|  |   0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x73, | ||||||
|  |   0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x6e, | ||||||
|  |   0x65, 0x77, 0x20, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, | ||||||
|  |   0x6e, 0x74, 0x28, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, | ||||||
|  |   0x2c, 0x20, 0x7b, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x20, | ||||||
|  |   0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x20, 0x7d, | ||||||
|  |   0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, | ||||||
|  |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x68, | ||||||
|  |   0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x67, 0x65, 0x6e, | ||||||
|  |   0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, | ||||||
|  |   0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, | ||||||
|  |   0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, | ||||||
|  |   0x67, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, | ||||||
|  |   0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, 0x20, 0x43, 0x75, | ||||||
|  |   0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x67, | ||||||
|  |   0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, | ||||||
|  |   0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x2c, 0x20, 0x7b, 0x20, 0x64, | ||||||
|  |   0x65, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, | ||||||
|  |   0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, | ||||||
|  |   0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, | ||||||
|  |   0x73, 0x20, 0x7d, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|  |   0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, | ||||||
|  |   0x28, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, | ||||||
|  |   0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, | ||||||
|   0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, |   0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, | ||||||
|   0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, |   0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, | ||||||
|   0x20, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, |   0x20, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, | ||||||
|   0x28, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x20, |   0x28, 0x22, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x2c, 0x20, | ||||||
|   0x7b, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x20, 0x63, 0x68, |   0x7b, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x20, 0x63, 0x68, | ||||||
|   0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x20, 0x7d, 0x29, 0x29, |   0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x69, 0x6d, | ||||||
|   0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, |   0x69, 0x6e, 0x67, 0x73, 0x20, 0x7d, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x68, 0x75, 0x6e, |   0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, | ||||||
|   0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, |   0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, | ||||||
|   0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, |   0x67, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, | ||||||
|   0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, 0x20, 0x43, 0x75, | ||||||
|   0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, |   0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, | ||||||
|   0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, |   0x6f, 0x6e, 0x65, 0x22, 0x2c, 0x20, 0x7b, 0x20, 0x64, 0x65, 0x74, 0x61, | ||||||
|   0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, 0x20, 0x43, 0x75, 0x73, 0x74, |   0x69, 0x6c, 0x3a, 0x20, 0x7b, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, | ||||||
|   0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x67, 0x65, 0x6e, |   0x74, 0x20, 0x7d, 0x20, 0x7d, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, | ||||||
|   0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, |   0x29, 0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, | ||||||
|   0x69, 0x6e, 0x67, 0x73, 0x22, 0x2c, 0x20, 0x7b, 0x20, 0x64, 0x65, 0x74, |   0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, | ||||||
|   0x61, 0x69, 0x6c, 0x3a, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, |   0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x2f, 0x2f, 0x20, 0x43, 0x61, 0x6c, | ||||||
|   0x61, 0x74, 0x61, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, |   0x6c, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x2c, 0x20, 0x72, 0x65, 0x74, | ||||||
|   0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, |   0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x73, | ||||||
|   0x7d, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, |   0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, | ||||||
|   0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, |   0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, | ||||||
|   0x68, 0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x69, |   0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x20, 0x74, 0x65, 0x78, | ||||||
|   0x6d, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, |   0x74, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x65, 0x73, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, |   0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, | ||||||
|   0x72, 0x67, 0x65, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, |   0x20, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x2f, | ||||||
|   0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, 0x20, 0x43, |   0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, | ||||||
|   0x75, 0x73, 0x74, 0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x22, |   0x3a, 0x0a, 0x2f, 0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x2c, 0x20, 0x7b, 0x20, |   0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, | ||||||
|   0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x20, 0x63, 0x68, 0x75, 0x6e, |   0x28, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x29, 0x2e, 0x74, 0x68, 0x65, | ||||||
|   0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x74, 0x69, 0x6d, 0x69, 0x6e, |   0x6e, 0x28, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x20, | ||||||
|   0x67, 0x73, 0x20, 0x7d, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, |   0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, |   0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, | ||||||
|   0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, |   0x72, 0x69, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, | ||||||
|   0x74, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x45, 0x76, |   0x29, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, | ||||||
|   0x65, 0x6e, 0x74, 0x28, 0x6e, 0x65, 0x77, 0x20, 0x43, 0x75, 0x73, 0x74, |   0x2f, 0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x72, | ||||||
|   0x6f, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x64, 0x6f, 0x6e, |   0x0a, 0x2f, 0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, | ||||||
|   0x65, 0x22, 0x2c, 0x20, 0x7b, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, |   0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, | ||||||
|   0x3a, 0x20, 0x7b, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, |   0x20, 0x3d, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x6c, 0x6c, 0x61, | ||||||
|   0x7d, 0x20, 0x7d, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x29, 0x28, |   0x6d, 0x61, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x70, 0x72, | ||||||
|   0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, |   0x6f, 0x6d, 0x70, 0x74, 0x29, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x3b, |   0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x72, | ||||||
|   0x0a, 0x7d, 0x0a, 0x0a, 0x2f, 0x2f, 0x20, 0x43, 0x61, 0x6c, 0x6c, 0x20, |   0x69, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, | ||||||
|   0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x2c, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, |   0x0a, 0x2f, 0x2f, 0x0a, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, | ||||||
|   0x6e, 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x20, |   0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x50, 0x72, | ||||||
|   0x74, 0x68, 0x61, 0x74, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, |   0x6f, 0x6d, 0x69, 0x73, 0x65, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x72, 0x6f, | ||||||
|   0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, |   0x6d, 0x70, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, | ||||||
|   0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2e, |   0x3d, 0x20, 0x7b, 0x7d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, | ||||||
|   0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, |   0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, | ||||||
|   0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x73, |   0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x65, 0x77, | ||||||
|   0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x2f, 0x2f, 0x0a, |   0x20, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x61, 0x73, 0x79, | ||||||
|   0x2f, 0x2f, 0x20, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0a, |   0x6e, 0x63, 0x20, 0x28, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x2c, | ||||||
|   0x2f, 0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6c, |   0x20, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x29, 0x20, 0x3d, 0x3e, 0x20, | ||||||
|   0x61, 0x6d, 0x61, 0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x70, |   0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, | ||||||
|   0x72, 0x6f, 0x6d, 0x70, 0x74, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, |   0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0a, | ||||||
|   0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x3d, 0x3e, |   0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, | ||||||
|   0x20, 0x7b, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |   0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x77, 0x61, 0x69, | ||||||
|   0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x72, 0x69, |   0x74, 0x20, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x68, 0x75, | ||||||
|   0x74, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x0a, |   0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x28, | ||||||
|   0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, 0x2f, 0x2f, |   0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, | ||||||
|   0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x72, 0x0a, 0x2f, |   0x6d, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x29, 0x29, | ||||||
|   0x2f, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, |   0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, | ||||||
|   0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, |   0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x63, 0x68, | ||||||
|   0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, |   0x75, 0x6e, 0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x63, 0x6f, 0x6e, | ||||||
|   0x50, 0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x70, 0x72, 0x6f, 0x6d, |   0x74, 0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||||||
|   0x70, 0x74, 0x29, 0x0a, 0x2f, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, |   0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x6f, | ||||||
|   0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x72, 0x69, 0x74, |   0x6c, 0x76, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, | ||||||
|   0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x2f, |   0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x63, 0x61, 0x74, 0x63, | ||||||
|   0x2f, 0x0a, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, |   0x68, 0x20, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0a, | ||||||
|   0x73, 0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x50, 0x72, 0x6f, 0x6d, |   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, | ||||||
|   0x69, 0x73, 0x65, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x6d, 0x70, |   0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, | ||||||
|   0x74, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x3d, 0x20, |   0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, | ||||||
|   0x7b, 0x7d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x3d, |   0x0a, 0x2f, 0x2a, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x28, 0x64, 0x65, 0x70, | ||||||
|   0x20, 0x7b, 0x7d, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, |   0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x29, 0x0a, 0x20, 0x2a, 0x2f, | ||||||
|   0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x50, |   0x0a, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, | ||||||
|   0x72, 0x6f, 0x6d, 0x69, 0x73, 0x65, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, |   0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x6c, | ||||||
|   0x20, 0x28, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x2c, 0x20, 0x72, |   0x65, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, | ||||||
|   0x65, 0x6a, 0x65, 0x63, 0x74, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, |   0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, |   0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x63, 0x61, 0x6c, | ||||||
|   0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0a, 0x20, 0x20, |   0x6c, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, | ||||||
|   0x20, 0x20, 0x74, 0x72, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, |  | ||||||
|   0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, |   0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, | ||||||
|   0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, |   0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, | ||||||
|   0x20, 0x6f, 0x66, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x28, 0x70, 0x72, |   0x20, 0x6f, 0x66, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x28, 0x70, 0x61, | ||||||
|   0x6f, 0x6d, 0x70, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, |   0x72, 0x61, 0x6d, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x2c, | ||||||
|   0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x29, 0x29, 0x20, 0x7b, |   0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x7b, 0x20, 0x63, | ||||||
|   0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, |   0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x7d, 0x29, | ||||||
|   0x74, 0x65, 0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x63, 0x68, 0x75, 0x6e, |   0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x6c, 0x6c, | ||||||
|   0x6b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, |   0x62, 0x61, 0x63, 0x6b, 0x28, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x29, 0x3b, | ||||||
|   0x6e, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, |   0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x2f, 0x2f, 0x20, 0x47, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, |   0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, | ||||||
|   0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x29, 0x3b, 0x0a, |   0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x63, 0x61, 0x74, 0x63, 0x68, 0x20, |   0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x20, 0x54, | ||||||
|   0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, |   0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, | ||||||
|   0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x28, 0x65, |   0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, | ||||||
|   0x72, 0x72, 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, |   0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, | ||||||
|   0x0a, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x2f, |   0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, | ||||||
|   0x2a, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x28, 0x64, 0x65, 0x70, 0x72, 0x65, |   0x20, 0x73, 0x6f, 0x20, 0x6f, 0x6e, 0x2e, 0x0a, 0x65, 0x78, 0x70, 0x6f, | ||||||
|   0x63, 0x61, 0x74, 0x65, 0x64, 0x29, 0x0a, 0x20, 0x2a, 0x2f, 0x0a, 0x65, |   0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x6c, 0x61, | ||||||
|   0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, |   0x6d, 0x61, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x20, | ||||||
|   0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, |   0x3d, 0x20, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x28, 0x29, 0x20, 0x3d, | ||||||
|   0x65, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x28, 0x70, |   0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x67, | ||||||
|   0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, |  | ||||||
|   0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2c, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, |  | ||||||
|   0x61, 0x63, 0x6b, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, |  | ||||||
|   0x66, 0x6f, 0x72, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x28, 0x63, |  | ||||||
|   0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x6f, |  | ||||||
|   0x66, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x28, 0x70, 0x61, 0x72, 0x61, |  | ||||||
|   0x6d, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x2c, 0x20, 0x70, |  | ||||||
|   0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x7b, 0x20, 0x63, 0x6f, 0x6e, |  | ||||||
|   0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x7d, 0x29, 0x29, 0x20, |  | ||||||
|   0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, |  | ||||||
|   0x63, 0x6b, 0x28, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x29, 0x3b, 0x0a, 0x20, |  | ||||||
|   0x20, 0x7d, 0x0a, 0x7d, 0x0a, 0x0a, 0x2f, 0x2f, 0x20, 0x47, 0x65, 0x74, |  | ||||||
|   0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x20, 0x69, |  | ||||||
|   0x6e, 0x66, 0x6f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, |  | ||||||
|   0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x69, |  | ||||||
|   0x73, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, |  | ||||||
|   0x66, 0x6f, 0x72, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, |  | ||||||
|   0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, |  | ||||||
|   0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, |  | ||||||
|   0x6f, 0x20, 0x6f, 0x6e, 0x2e, 0x0a, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, |  | ||||||
|   0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, |  | ||||||
|   0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x49, 0x6e, 0x66, 0x6f, 0x20, 0x3d, 0x20, |  | ||||||
|   0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x28, 0x29, 0x20, 0x3d, 0x3e, 0x20, |  | ||||||
|   0x7b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x67, 0x65, 0x6e, |  | ||||||
|   0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, |  | ||||||
|   0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, |  | ||||||
|   0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x20, |  | ||||||
|   0x3d, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, |  | ||||||
|   0x68, 0x28, 0x22, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x22, 0x29, 0x2e, |  | ||||||
|   0x74, 0x68, 0x65, 0x6e, 0x28, 0x72, 0x20, 0x3d, 0x3e, 0x20, 0x72, 0x2e, |  | ||||||
|   0x6a, 0x73, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, |  | ||||||
|   0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, |  | ||||||
|   0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x70, |  | ||||||
|   0x72, 0x6f, 0x70, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, |  | ||||||
|   0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, |  | ||||||
|   0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x0a, 0x20, 0x20, |  | ||||||
|   0x7d, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, |  | ||||||
|   0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, |   0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, | ||||||
|   0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x0a, 0x7d, 0x0a |   0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, | ||||||
|  |   0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x70, | ||||||
|  |   0x73, 0x20, 0x3d, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, | ||||||
|  |   0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x22, | ||||||
|  |   0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x72, 0x20, 0x3d, 0x3e, 0x20, | ||||||
|  |   0x72, 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x28, 0x29, 0x29, 0x3b, 0x0a, 0x20, | ||||||
|  |   0x20, 0x20, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, | ||||||
|  |   0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, | ||||||
|  |   0x20, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x2e, 0x64, 0x65, 0x66, 0x61, 0x75, | ||||||
|  |   0x6c, 0x74, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, | ||||||
|  |   0x6e, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x0a, | ||||||
|  |   0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, | ||||||
|  |   0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, | ||||||
|  |   0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x0a, 0x7d, 0x0a | ||||||
| }; | }; | ||||||
| unsigned int completion_js_len = 5782; | unsigned int completion_js_len = 5796; | ||||||
|   | |||||||
| @@ -96,17 +96,17 @@ export async function* llama(prompt, params = {}, config = {}) { | |||||||
|             } |             } | ||||||
|           } |           } | ||||||
|           if (result.error) { |           if (result.error) { | ||||||
|  |             try { | ||||||
|               result.error = JSON.parse(result.error); |               result.error = JSON.parse(result.error); | ||||||
|             if (result.error.content.includes('slot unavailable')) { |               if (result.error.message.includes('slot unavailable')) { | ||||||
|                 // Throw an error to be caught by upstream callers |                 // Throw an error to be caught by upstream callers | ||||||
|                 throw new Error('slot unavailable'); |                 throw new Error('slot unavailable'); | ||||||
|               } else { |               } else { | ||||||
|               console.error(`llama.cpp error: ${result.error.content}`); |                 console.error(`llama.cpp error [${result.error.code} - ${result.error.type}]: ${result.error.message}`); | ||||||
|               } |               } | ||||||
|  |             } catch(e) { | ||||||
|  |               console.error(`llama.cpp error ${result.error}`) | ||||||
|             } |             } | ||||||
|           if (result.error) { |  | ||||||
|             result.error = JSON.parse(result.error); |  | ||||||
|             console.error(`llama.cpp error: ${result.error.content}`); |  | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -396,7 +396,7 @@ struct server_queue { | |||||||
|     // callback functions |     // callback functions | ||||||
|     std::function<void(server_task       &)> callback_new_task; |     std::function<void(server_task       &)> callback_new_task; | ||||||
|     std::function<void(server_task_multi &)> callback_finish_multitask; |     std::function<void(server_task_multi &)> callback_finish_multitask; | ||||||
|     std::function<void(void)>                callback_run_slots; |     std::function<void(void)>                callback_update_slots; | ||||||
|  |  | ||||||
|     // Add a new task to the end of the queue |     // Add a new task to the end of the queue | ||||||
|     int post(server_task task) { |     int post(server_task task) { | ||||||
| @@ -435,8 +435,8 @@ struct server_queue { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Register the function to be called when all slots data is ready to be processed |     // Register the function to be called when all slots data is ready to be processed | ||||||
|     void on_run_slots(std::function<void(void)> callback) { |     void on_update_slots(std::function<void(void)> callback) { | ||||||
|         callback_run_slots = std::move(callback); |         callback_update_slots = std::move(callback); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Call when the state of one slot is changed |     // Call when the state of one slot is changed | ||||||
| @@ -461,7 +461,7 @@ struct server_queue { | |||||||
|      * - Wait until a new task arrives |      * - Wait until a new task arrives | ||||||
|      * - Process the task (i.e. maybe copy data into slot) |      * - Process the task (i.e. maybe copy data into slot) | ||||||
|      * - Check if multitask is finished |      * - Check if multitask is finished | ||||||
|      * - Run all slots |      * - Update all slots | ||||||
|      */ |      */ | ||||||
|     void start_loop() { |     void start_loop() { | ||||||
|         running = true; |         running = true; | ||||||
| @@ -499,9 +499,9 @@ struct server_queue { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             // all tasks in the current loop is processed, slots data is now ready |             // all tasks in the current loop is processed, slots data is now ready | ||||||
|             LOG_VERBOSE("callback_run_slots", {}); |             LOG_VERBOSE("callback_update_slots", {}); | ||||||
|  |  | ||||||
|             callback_run_slots(); |             callback_update_slots(); | ||||||
|  |  | ||||||
|             LOG_VERBOSE("wait for new task", {}); |             LOG_VERBOSE("wait for new task", {}); | ||||||
|             { |             { | ||||||
| @@ -805,9 +805,10 @@ struct server_context { | |||||||
|         return last_used; |         return last_used; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool launch_slot_with_data(server_slot & slot, json data) const { |     bool launch_slot_with_task(server_slot & slot, const server_task & task) { | ||||||
|         slot_params default_params; |         slot_params default_params; | ||||||
|         llama_sampling_params default_sparams; |         llama_sampling_params default_sparams; | ||||||
|  |         auto & data = task.data; | ||||||
|  |  | ||||||
|         if (data.count("__oaicompat") != 0) { |         if (data.count("__oaicompat") != 0) { | ||||||
|             slot.oaicompat = true; |             slot.oaicompat = true; | ||||||
| @@ -864,10 +865,15 @@ struct server_context { | |||||||
|         { |         { | ||||||
|             const auto & prompt = data.find("prompt"); |             const auto & prompt = data.find("prompt"); | ||||||
|             if (prompt == data.end()) { |             if (prompt == data.end()) { | ||||||
|                 slot.prompt = ""; |                 send_error(task, "Either \"prompt\" or \"messages\" must be provided", ERROR_TYPE_INVALID_REQUEST); | ||||||
|  |                 return false; | ||||||
|             } else { |             } else { | ||||||
|                 slot.prompt = *prompt; |                 slot.prompt = *prompt; | ||||||
|             } |             } | ||||||
|  |             if (slot.prompt.is_array() && slot.prompt.size() == 0) { | ||||||
|  |                 send_error(task, "\"prompt\" cannot be an empty array", ERROR_TYPE_INVALID_REQUEST); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // penalize user-provided tokens |         // penalize user-provided tokens | ||||||
| @@ -926,6 +932,7 @@ struct server_context { | |||||||
|             if (logit_bias != data.end() && logit_bias->is_array()) { |             if (logit_bias != data.end() && logit_bias->is_array()) { | ||||||
|                 const int n_vocab = llama_n_vocab(model); |                 const int n_vocab = llama_n_vocab(model); | ||||||
|                 for (const auto & el : *logit_bias) { |                 for (const auto & el : *logit_bias) { | ||||||
|  |                     // TODO: we may want to throw errors here, in case "el" is incorrect | ||||||
|                     if (el.is_array() && el.size() == 2) { |                     if (el.is_array() && el.size() == 2) { | ||||||
|                         float bias; |                         float bias; | ||||||
|                         if (el[1].is_number()) { |                         if (el[1].is_number()) { | ||||||
| @@ -985,6 +992,11 @@ struct server_context { | |||||||
|                 llama_sampling_free(slot.ctx_sampling); |                 llama_sampling_free(slot.ctx_sampling); | ||||||
|             } |             } | ||||||
|             slot.ctx_sampling = llama_sampling_init(slot.sparams); |             slot.ctx_sampling = llama_sampling_init(slot.sparams); | ||||||
|  |             if (slot.ctx_sampling == nullptr) { | ||||||
|  |                 // for now, the only error that may happen here is invalid grammar | ||||||
|  |                 send_error(task, "Failed to parse grammar", ERROR_TYPE_INVALID_REQUEST); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|             llama_set_rng_seed(ctx, slot.params.seed); |             llama_set_rng_seed(ctx, slot.params.seed); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1226,15 +1238,23 @@ struct server_context { | |||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void send_error(const server_task & task, const std::string & error) { |     void send_error(const server_task & task, const std::string & error, const enum error_type type = ERROR_TYPE_SERVER) { | ||||||
|         LOG_TEE("task %i - error: %s\n", task.id, error.c_str()); |         send_error(task.id, task.id_multi, error, type); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void send_error(const server_slot & slot, const std::string & error, const enum error_type type = ERROR_TYPE_SERVER) { | ||||||
|  |         send_error(slot.id_task, slot.id_multi, error, type); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void send_error(const int id_task, const int id_multi, const std::string & error, const enum error_type type = ERROR_TYPE_SERVER) { | ||||||
|  |         LOG_TEE("task %i - error: %s\n", id_task, error.c_str()); | ||||||
|  |  | ||||||
|         server_task_result res; |         server_task_result res; | ||||||
|         res.id       = task.id; |         res.id       = id_task; | ||||||
|         res.id_multi = task.id_multi; |         res.id_multi = id_multi; | ||||||
|         res.stop     = false; |         res.stop     = false; | ||||||
|         res.error    = true; |         res.error    = true; | ||||||
|         res.data     = { { "content", error } }; |         res.data     = format_error_response(error, type); | ||||||
|  |  | ||||||
|         queue_results.send(res); |         queue_results.send(res); | ||||||
|     } |     } | ||||||
| @@ -1468,9 +1488,8 @@ struct server_context { | |||||||
|                     slot->infill    = task.infill; |                     slot->infill    = task.infill; | ||||||
|                     slot->embedding = task.embedding; |                     slot->embedding = task.embedding; | ||||||
|  |  | ||||||
|                     if (!launch_slot_with_data(*slot, task.data)) { |                     if (!launch_slot_with_task(*slot, task)) { | ||||||
|                         // send error result |                         LOG_ERROR("error while launching slot", task.data); | ||||||
|                         send_error(task, "internal_error"); |  | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|                 } break; |                 } break; | ||||||
| @@ -1587,7 +1606,7 @@ struct server_context { | |||||||
|         queue_results.send(result); |         queue_results.send(result); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool update_slots() { |     void update_slots() { | ||||||
|         if (system_need_update) { |         if (system_need_update) { | ||||||
|             system_prompt_update(); |             system_prompt_update(); | ||||||
|         } |         } | ||||||
| @@ -1630,7 +1649,7 @@ struct server_context { | |||||||
|                     kv_cache_clear(); |                     kv_cache_clear(); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 return true; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1975,8 +1994,7 @@ struct server_context { | |||||||
|  |  | ||||||
|         if (batch.n_tokens == 0) { |         if (batch.n_tokens == 0) { | ||||||
|             LOG_VERBOSE("no tokens to decode", {}); |             LOG_VERBOSE("no tokens to decode", {}); | ||||||
|  |             return; | ||||||
|             return true; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         LOG_VERBOSE("decoding batch", { |         LOG_VERBOSE("decoding batch", { | ||||||
| @@ -2033,7 +2051,13 @@ struct server_context { | |||||||
|                 if (n_batch == 1 || ret < 0) { |                 if (n_batch == 1 || ret < 0) { | ||||||
|                     // if you get here, it means the KV cache is full - try increasing it via the context size |                     // if you get here, it means the KV cache is full - try increasing it via the context size | ||||||
|                     LOG_TEE("%s : failed to decode the batch, n_batch = %d, ret = %d\n", __func__, n_batch, ret); |                     LOG_TEE("%s : failed to decode the batch, n_batch = %d, ret = %d\n", __func__, n_batch, ret); | ||||||
|                     return false; |                     for (auto & slot : slots) { | ||||||
|  |                         slot.state = SLOT_STATE_PROCESSING; | ||||||
|  |                         slot.command = SLOT_COMMAND_NONE; | ||||||
|  |                         slot.release(); | ||||||
|  |                         send_error(slot, "Input prompt is too big compared to KV size. Please try increasing KV size."); | ||||||
|  |                     } | ||||||
|  |                     break; // break loop of n_batch | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 LOG_TEE("%s : failed to find free space in the KV cache, retrying with smaller n_batch = %d\n", __func__, n_batch / 2); |                 LOG_TEE("%s : failed to find free space in the KV cache, retrying with smaller n_batch = %d\n", __func__, n_batch / 2); | ||||||
| @@ -2042,12 +2066,12 @@ struct server_context { | |||||||
|                 n_batch /= 2; |                 n_batch /= 2; | ||||||
|                 i -= n_batch; |                 i -= n_batch; | ||||||
|  |  | ||||||
|                 continue; |                 continue; // continue loop of n_batch | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             for (auto & slot : slots) { |             for (auto & slot : slots) { | ||||||
|                 if (slot.state != SLOT_STATE_PROCESSING || slot.i_batch < (int) i || slot.i_batch >= (int) (i + n_tokens)) { |                 if (slot.state != SLOT_STATE_PROCESSING || slot.i_batch < (int) i || slot.i_batch >= (int) (i + n_tokens)) { | ||||||
|                     continue; |                     continue; // continue loop of slots | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // prompt evaluated for embedding |                 // prompt evaluated for embedding | ||||||
| @@ -2055,7 +2079,7 @@ struct server_context { | |||||||
|                     send_embedding(slot, batch_view); |                     send_embedding(slot, batch_view); | ||||||
|                     slot.release(); |                     slot.release(); | ||||||
|                     slot.i_batch = -1; |                     slot.i_batch = -1; | ||||||
|                     continue; |                     continue; // continue loop of slots | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 completion_token_output result; |                 completion_token_output result; | ||||||
| @@ -2097,9 +2121,7 @@ struct server_context { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         LOG_VERBOSE("slots updated", {}); |         LOG_VERBOSE("run slots completed", {}); | ||||||
|  |  | ||||||
|         return true; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     json model_meta() const { |     json model_meta() const { | ||||||
| @@ -2745,32 +2767,32 @@ int main(int argc, char ** argv) { | |||||||
|  |  | ||||||
|     svr->set_logger(log_server_request); |     svr->set_logger(log_server_request); | ||||||
|  |  | ||||||
|     svr->set_exception_handler([](const httplib::Request &, httplib::Response & res, std::exception_ptr ep) { |     auto res_error = [](httplib::Response & res, json error_data) { | ||||||
|         const char fmt[] = "500 Internal Server Error\n%s"; |         json final_response {{"error", error_data}}; | ||||||
|  |         res.set_content(final_response.dump(), "application/json; charset=utf-8"); | ||||||
|  |         res.status = json_value(error_data, "code", 500); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|         char buf[BUFSIZ]; |     svr->set_exception_handler([&res_error](const httplib::Request &, httplib::Response & res, std::exception_ptr ep) { | ||||||
|  |         std::string message; | ||||||
|         try { |         try { | ||||||
|             std::rethrow_exception(std::move(ep)); |             std::rethrow_exception(std::move(ep)); | ||||||
|         } catch (std::exception &e) { |         } catch (std::exception & e) { | ||||||
|             snprintf(buf, sizeof(buf), fmt, e.what()); |             message = e.what(); | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
|             snprintf(buf, sizeof(buf), fmt, "Unknown Exception"); |             message = "Unknown Exception"; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         res.set_content(buf, "text/plain; charset=utf-8"); |         json formatted_error = format_error_response(message, ERROR_TYPE_SERVER); | ||||||
|         res.status = 500; |         LOG_VERBOSE("Got exception", formatted_error); | ||||||
|  |         res_error(res, formatted_error); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     svr->set_error_handler([](const httplib::Request &, httplib::Response & res) { |     svr->set_error_handler([&res_error](const httplib::Request &, httplib::Response & res) { | ||||||
|         if (res.status == 401) { |  | ||||||
|             res.set_content("Unauthorized", "text/plain; charset=utf-8"); |  | ||||||
|         } |  | ||||||
|         if (res.status == 400) { |  | ||||||
|             res.set_content("Invalid request", "text/plain; charset=utf-8"); |  | ||||||
|         } |  | ||||||
|         if (res.status == 404) { |         if (res.status == 404) { | ||||||
|             res.set_content("File Not Found", "text/plain; charset=utf-8"); |             res_error(res, format_error_response("File Not Found", ERROR_TYPE_NOT_FOUND)); | ||||||
|         } |         } | ||||||
|  |         // for other error codes, we skip processing here because it's already done by res_error() | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // set timeouts and change hostname and port |     // set timeouts and change hostname and port | ||||||
| @@ -2835,7 +2857,7 @@ int main(int argc, char ** argv) { | |||||||
|     // Middlewares |     // Middlewares | ||||||
|     // |     // | ||||||
|  |  | ||||||
|     auto middleware_validate_api_key = [&sparams](const httplib::Request & req, httplib::Response & res) { |     auto middleware_validate_api_key = [&sparams, &res_error](const httplib::Request & req, httplib::Response & res) { | ||||||
|         // TODO: should we apply API key to all endpoints, including "/health" and "/models"? |         // TODO: should we apply API key to all endpoints, including "/health" and "/models"? | ||||||
|         static const std::set<std::string> protected_endpoints = { |         static const std::set<std::string> protected_endpoints = { | ||||||
|             "/props", |             "/props", | ||||||
| @@ -2876,8 +2898,7 @@ int main(int argc, char ** argv) { | |||||||
|         // API key is invalid or not provided |         // API key is invalid or not provided | ||||||
|         // TODO: make another middleware for CORS related logic |         // TODO: make another middleware for CORS related logic | ||||||
|         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); |         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); | ||||||
|         res.set_content("Unauthorized: Invalid API Key", "text/plain; charset=utf-8"); |         res_error(res, format_error_response("Invalid API Key", ERROR_TYPE_AUTHENTICATION)); | ||||||
|         res.status = 401; // Unauthorized |  | ||||||
|  |  | ||||||
|         LOG_WARNING("Unauthorized: Invalid API Key", {}); |         LOG_WARNING("Unauthorized: Invalid API Key", {}); | ||||||
|  |  | ||||||
| @@ -2940,21 +2961,18 @@ int main(int argc, char ** argv) { | |||||||
|                 } |                 } | ||||||
|             case SERVER_STATE_LOADING_MODEL: |             case SERVER_STATE_LOADING_MODEL: | ||||||
|                 { |                 { | ||||||
|                     res.set_content(R"({"status": "loading model"})", "application/json"); |                     res_error(res, format_error_response("Loading model", ERROR_TYPE_UNAVAILABLE)); | ||||||
|                     res.status = 503; // HTTP Service Unavailable |  | ||||||
|                 } break; |                 } break; | ||||||
|             case SERVER_STATE_ERROR: |             case SERVER_STATE_ERROR: | ||||||
|                 { |                 { | ||||||
|                     res.set_content(R"({"status": "error", "error": "Model failed to load"})", "application/json"); |                     res_error(res, format_error_response("Model failed to load", ERROR_TYPE_SERVER)); | ||||||
|                     res.status = 500; // HTTP Internal Server Error |  | ||||||
|                 } break; |                 } break; | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const auto handle_slots = [&](const httplib::Request &, httplib::Response & res) { |     const auto handle_slots = [&](const httplib::Request &, httplib::Response & res) { | ||||||
|         if (!sparams.slots_endpoint) { |         if (!sparams.slots_endpoint) { | ||||||
|             res.status = 501; |             res_error(res, format_error_response("This server does not support slots endpoint.", ERROR_TYPE_NOT_SUPPORTED)); | ||||||
|             res.set_content("This server does not support slots endpoint.", "text/plain; charset=utf-8"); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -2978,8 +2996,7 @@ int main(int argc, char ** argv) { | |||||||
|  |  | ||||||
|     const auto handle_metrics = [&](const httplib::Request &, httplib::Response & res) { |     const auto handle_metrics = [&](const httplib::Request &, httplib::Response & res) { | ||||||
|         if (!sparams.metrics_endpoint) { |         if (!sparams.metrics_endpoint) { | ||||||
|             res.status = 501; |             res_error(res, format_error_response("This server does not support metrics endpoint.", ERROR_TYPE_NOT_SUPPORTED)); | ||||||
|             res.set_content("This server does not support metrics endpoint.", "text/plain; charset=utf-8"); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -3090,7 +3107,7 @@ int main(int argc, char ** argv) { | |||||||
|         res.set_content(data.dump(), "application/json; charset=utf-8"); |         res.set_content(data.dump(), "application/json; charset=utf-8"); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const auto handle_completions = [&ctx_server](const httplib::Request & req, httplib::Response & res) { |     const auto handle_completions = [&ctx_server, &res_error](const httplib::Request & req, httplib::Response & res) { | ||||||
|         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); |         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); | ||||||
|  |  | ||||||
|         json data = json::parse(req.body); |         json data = json::parse(req.body); | ||||||
| @@ -3105,8 +3122,7 @@ int main(int argc, char ** argv) { | |||||||
|             if (!result.error && result.stop) { |             if (!result.error && result.stop) { | ||||||
|                 res.set_content(result.data.dump(-1, ' ', false, json::error_handler_t::replace), "application/json; charset=utf-8"); |                 res.set_content(result.data.dump(-1, ' ', false, json::error_handler_t::replace), "application/json; charset=utf-8"); | ||||||
|             } else { |             } else { | ||||||
|                 res.status = 500; |                 res_error(res, result.data); | ||||||
|                 res.set_content(result.data["content"], "text/plain; charset=utf-8"); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             ctx_server.queue_results.remove_waiting_task_id(id_task); |             ctx_server.queue_results.remove_waiting_task_id(id_task); | ||||||
| @@ -3186,7 +3202,7 @@ int main(int argc, char ** argv) { | |||||||
|         res.set_content(models.dump(), "application/json; charset=utf-8"); |         res.set_content(models.dump(), "application/json; charset=utf-8"); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const auto handle_chat_completions = [&ctx_server, &sparams](const httplib::Request & req, httplib::Response & res) { |     const auto handle_chat_completions = [&ctx_server, &sparams, &res_error](const httplib::Request & req, httplib::Response & res) { | ||||||
|         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); |         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); | ||||||
|         json data = oaicompat_completion_params_parse(ctx_server.model, json::parse(req.body), sparams.chat_template); |         json data = oaicompat_completion_params_parse(ctx_server.model, json::parse(req.body), sparams.chat_template); | ||||||
|  |  | ||||||
| @@ -3204,8 +3220,7 @@ int main(int argc, char ** argv) { | |||||||
|  |  | ||||||
|                 res.set_content(result_oai.dump(-1, ' ', false, json::error_handler_t::replace), "application/json; charset=utf-8"); |                 res.set_content(result_oai.dump(-1, ' ', false, json::error_handler_t::replace), "application/json; charset=utf-8"); | ||||||
|             } else { |             } else { | ||||||
|                 res.status = 500; |                 res_error(res, result.data); | ||||||
|                 res.set_content(result.data["content"], "text/plain; charset=utf-8"); |  | ||||||
|             } |             } | ||||||
|             ctx_server.queue_results.remove_waiting_task_id(id_task); |             ctx_server.queue_results.remove_waiting_task_id(id_task); | ||||||
|         } else { |         } else { | ||||||
| @@ -3259,7 +3274,7 @@ int main(int argc, char ** argv) { | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const auto handle_infill = [&ctx_server](const httplib::Request & req, httplib::Response & res) { |     const auto handle_infill = [&ctx_server, &res_error](const httplib::Request & req, httplib::Response & res) { | ||||||
|         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); |         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); | ||||||
|  |  | ||||||
|         json data = json::parse(req.body); |         json data = json::parse(req.body); | ||||||
| @@ -3274,8 +3289,7 @@ int main(int argc, char ** argv) { | |||||||
|             if (!result.error && result.stop) { |             if (!result.error && result.stop) { | ||||||
|                 res.set_content(result.data.dump(-1, ' ', false, json::error_handler_t::replace), "application/json; charset=utf-8"); |                 res.set_content(result.data.dump(-1, ' ', false, json::error_handler_t::replace), "application/json; charset=utf-8"); | ||||||
|             } else { |             } else { | ||||||
|                 res.status = 404; |                 res_error(res, result.data); | ||||||
|                 res.set_content(result.data["content"], "text/plain; charset=utf-8"); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             ctx_server.queue_results.remove_waiting_task_id(id_task); |             ctx_server.queue_results.remove_waiting_task_id(id_task); | ||||||
| @@ -3346,7 +3360,7 @@ int main(int argc, char ** argv) { | |||||||
|         return res.set_content(data.dump(), "application/json; charset=utf-8"); |         return res.set_content(data.dump(), "application/json; charset=utf-8"); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const auto handle_embeddings = [¶ms, &ctx_server](const httplib::Request & req, httplib::Response & res) { |     const auto handle_embeddings = [¶ms, &ctx_server, &res_error](const httplib::Request & req, httplib::Response & res) { | ||||||
|         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); |         res.set_header("Access-Control-Allow-Origin", req.get_header_value("Origin")); | ||||||
|         if (!params.embedding) { |         if (!params.embedding) { | ||||||
|             res.status = 501; |             res.status = 501; | ||||||
| @@ -3375,8 +3389,8 @@ int main(int argc, char ** argv) { | |||||||
|             std::string content = body["content"]; |             std::string content = body["content"]; | ||||||
|             prompts.push_back(content); |             prompts.push_back(content); | ||||||
|         } else { |         } else { | ||||||
|             // TODO @ngxson : should return an error here |             res_error(res, format_error_response("\"input\" or \"content\" must be provided", ERROR_TYPE_INVALID_REQUEST)); | ||||||
|             prompts.push_back(""); |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // process all prompts |         // process all prompts | ||||||
| @@ -3392,9 +3406,14 @@ int main(int argc, char ** argv) { | |||||||
|             // get the result |             // get the result | ||||||
|             server_task_result result = ctx_server.queue_results.recv(id_task); |             server_task_result result = ctx_server.queue_results.recv(id_task); | ||||||
|             ctx_server.queue_results.remove_waiting_task_id(id_task); |             ctx_server.queue_results.remove_waiting_task_id(id_task); | ||||||
|  |             if (!result.error) { | ||||||
|                 // append to the responses |                 // append to the responses | ||||||
|                 responses.push_back(result.data); |                 responses.push_back(result.data); | ||||||
|  |             } else { | ||||||
|  |                 // error received, ignore everything else | ||||||
|  |                 res_error(res, result.data); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // write JSON response |         // write JSON response | ||||||
| @@ -3488,7 +3507,7 @@ int main(int argc, char ** argv) { | |||||||
|         &server_context::process_single_task, &ctx_server, std::placeholders::_1)); |         &server_context::process_single_task, &ctx_server, std::placeholders::_1)); | ||||||
|     ctx_server.queue_tasks.on_finish_multitask(std::bind( |     ctx_server.queue_tasks.on_finish_multitask(std::bind( | ||||||
|         &server_context::on_finish_multitask, &ctx_server, std::placeholders::_1)); |         &server_context::on_finish_multitask, &ctx_server, std::placeholders::_1)); | ||||||
|     ctx_server.queue_tasks.on_run_slots(std::bind( |     ctx_server.queue_tasks.on_update_slots(std::bind( | ||||||
|         &server_context::update_slots, &ctx_server)); |         &server_context::update_slots, &ctx_server)); | ||||||
|     ctx_server.queue_results.on_multitask_update(std::bind( |     ctx_server.queue_results.on_multitask_update(std::bind( | ||||||
|         &server_queue::update_multitask, |         &server_queue::update_multitask, | ||||||
|   | |||||||
| @@ -801,7 +801,7 @@ async def oai_chat_completions(user_prompt, | |||||||
|                 stream=enable_streaming, |                 stream=enable_streaming, | ||||||
|                 seed=seed |                 seed=seed | ||||||
|             ) |             ) | ||||||
|         except openai.error.APIError as e: |         except openai.error.AuthenticationError as e: | ||||||
|             if expect_api_error is not None and expect_api_error: |             if expect_api_error is not None and expect_api_error: | ||||||
|                 return 401 |                 return 401 | ||||||
|             else: |             else: | ||||||
|   | |||||||
| @@ -14,6 +14,17 @@ | |||||||
|  |  | ||||||
| using json = nlohmann::json; | using json = nlohmann::json; | ||||||
|  |  | ||||||
|  | // https://community.openai.com/t/openai-chat-list-of-error-codes-and-types/357791/11 | ||||||
|  | enum error_type { | ||||||
|  |     ERROR_TYPE_INVALID_REQUEST, | ||||||
|  |     ERROR_TYPE_AUTHENTICATION, | ||||||
|  |     ERROR_TYPE_SERVER, | ||||||
|  |     ERROR_TYPE_NOT_FOUND, | ||||||
|  |     ERROR_TYPE_PERMISSION, | ||||||
|  |     ERROR_TYPE_UNAVAILABLE, // custom error | ||||||
|  |     ERROR_TYPE_NOT_SUPPORTED, // custom error | ||||||
|  | }; | ||||||
|  |  | ||||||
| extern bool server_verbose; | extern bool server_verbose; | ||||||
| extern bool server_log_json; | extern bool server_log_json; | ||||||
|  |  | ||||||
| @@ -542,3 +553,43 @@ static json format_detokenized_response(const std::string & content) { | |||||||
|         {"content", content} |         {"content", content} | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static json format_error_response(const std::string & message, const enum error_type type) { | ||||||
|  |     std::string type_str; | ||||||
|  |     int code = 500; | ||||||
|  |     switch (type) { | ||||||
|  |         case ERROR_TYPE_INVALID_REQUEST: | ||||||
|  |             type_str = "invalid_request_error"; | ||||||
|  |             code = 400; | ||||||
|  |             break; | ||||||
|  |         case ERROR_TYPE_AUTHENTICATION: | ||||||
|  |             type_str = "authentication_error"; | ||||||
|  |             code = 401; | ||||||
|  |             break; | ||||||
|  |         case ERROR_TYPE_NOT_FOUND: | ||||||
|  |             type_str = "not_found_error"; | ||||||
|  |             code = 404; | ||||||
|  |             break; | ||||||
|  |         case ERROR_TYPE_SERVER: | ||||||
|  |             type_str = "server_error"; | ||||||
|  |             code = 500; | ||||||
|  |             break; | ||||||
|  |         case ERROR_TYPE_PERMISSION: | ||||||
|  |             type_str = "permission_error"; | ||||||
|  |             code = 403; | ||||||
|  |             break; | ||||||
|  |         case ERROR_TYPE_NOT_SUPPORTED: | ||||||
|  |             type_str = "not_supported_error"; | ||||||
|  |             code = 501; | ||||||
|  |             break; | ||||||
|  |         case ERROR_TYPE_UNAVAILABLE: | ||||||
|  |             type_str = "unavailable_error"; | ||||||
|  |             code = 503; | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |     return json { | ||||||
|  |         {"code", code}, | ||||||
|  |         {"message", message}, | ||||||
|  |         {"type", type_str}, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Xuan Son Nguyen
					Xuan Son Nguyen