llama.cpp
.devops
nix
apps.nix devshells.nix docker.nix jetson-support.nix nixpkgs-instances.nix package-gguf-py.nix package.nix python-scripts.nix scope.nix sif.nix.github
ISSUE_TEMPLATE
010-bug-compilation.yml 011-bug-results.yml 019-bug-misc.yml 020-enhancement.yml 030-research.yml 040-refactor.yml config.ymlworkflows
bench.yml.disabled build-cache.yml build-cmake-pkg.yml build-linux-cross.yml build.yml check-vendor.yml close-issue.yml copilot-setup-steps.yml docker.yml editorconfig.yml gguf-publish.yml labeler.yml pre-tokenizer-hashes.yml python-check-requirements.yml python-lint.yml python-type-check.yml release.yml server-metal.yml server-webui.yml server.yml update-ops-docs.yml winget.ymlbenches
cmake
arm64-apple-clang.cmake arm64-windows-llvm.cmake build-info.cmake common.cmake download-models.cmake git-vars.cmake license.cmake llama-config.cmake.in llama.pc.in riscv64-spacemit-linux-gnu-gcc.cmake x64-windows-llvm.cmakecommon
jinja
README.md caps.cpp caps.h lexer.cpp lexer.h parser.cpp parser.h runtime.cpp runtime.h string.cpp string.h utils.h value.cpp value.hdocs
multimodal
MobileVLM.md gemma3.md glmedge.md granitevision.md llava.md minicpmo2.6.md minicpmo4.0.md minicpmv2.5.md minicpmv2.6.md minicpmv4.0.md minicpmv4.5.mdops
BLAS.csv CANN.csv CPU.csv CUDA.csv Metal.csv OpenCL.csv SYCL.csv Vulkan.csv WebGPU.csv ZenDNN.csv zDNN.csvexamples
llama.android
app
src
lib
.gitignore build.gradle.kts consumer-rules.pro proguard-rules.promodel-conversion
scripts
causal
compare-embeddings-logits.sh compare-logits.py convert-model.sh modelcard.template run-casual-gen-embeddings-org.py run-converted-model-embeddings-logits.sh run-converted-model.sh run-org-model.pyembedding
compare-embeddings-logits.sh convert-model.sh modelcard.template run-converted-model.sh run-original-model.pyutils
__init__.py check-nmse.py common.py compare_tokens.py create-collection-add-model.sh curl-embedding-server.sh hf-add-model-to-collection.py hf-create-collection.py hf-create-model.py hf-upload-gguf-model.py inspect-converted-model.sh inspect-org-model.py perplexity-gen.sh perplexity-run-simple.sh perplexity-run.sh quantize.sh run-embedding-server.sh semantic_check.py tensor-info.pysycl
CMakeLists.txt README.md build.sh ls-sycl-device.cpp run-llama2.sh test.sh win-build-sycl.bat win-run-llama2.bat win-test.batggml
include
ggml-alloc.h ggml-backend.h ggml-blas.h ggml-cann.h ggml-cpp.h ggml-cpu.h ggml-cuda.h ggml-hexagon.h ggml-metal.h ggml-opencl.h ggml-opt.h ggml-rpc.h ggml-sycl.h ggml-virtgpu.h ggml-vulkan.h ggml-webgpu.h ggml-zdnn.h ggml-zendnn.h ggml.h gguf.hsrc
ggml-cann
CMakeLists.txt acl_tensor.cpp acl_tensor.h aclnn_ops.cpp aclnn_ops.h common.h ggml-cann.cppggml-cpu
CMakeLists.txt arch-fallback.h binary-ops.cpp binary-ops.h common.h ggml-cpu-impl.h ggml-cpu.c ggml-cpu.cpp hbm.cpp hbm.h ops.cpp ops.h quants.c quants.h repack.cpp repack.h simd-mappings.h traits.cpp traits.h unary-ops.cpp unary-ops.h vec.cpp vec.hggml-cuda
template-instances
fattn-mma-f16-instance-ncols1_1-ncols2_16.cu fattn-mma-f16-instance-ncols1_1-ncols2_32.cu fattn-mma-f16-instance-ncols1_1-ncols2_8.cu fattn-mma-f16-instance-ncols1_16-ncols2_1.cu fattn-mma-f16-instance-ncols1_16-ncols2_2.cu fattn-mma-f16-instance-ncols1_16-ncols2_4.cu fattn-mma-f16-instance-ncols1_2-ncols2_16.cu fattn-mma-f16-instance-ncols1_2-ncols2_32.cu fattn-mma-f16-instance-ncols1_2-ncols2_4.cu fattn-mma-f16-instance-ncols1_2-ncols2_8.cu fattn-mma-f16-instance-ncols1_32-ncols2_1.cu fattn-mma-f16-instance-ncols1_32-ncols2_2.cu fattn-mma-f16-instance-ncols1_4-ncols2_16.cu fattn-mma-f16-instance-ncols1_4-ncols2_2.cu fattn-mma-f16-instance-ncols1_4-ncols2_4.cu fattn-mma-f16-instance-ncols1_4-ncols2_8.cu fattn-mma-f16-instance-ncols1_64-ncols2_1.cu fattn-mma-f16-instance-ncols1_8-ncols2_1.cu fattn-mma-f16-instance-ncols1_8-ncols2_2.cu fattn-mma-f16-instance-ncols1_8-ncols2_4.cu fattn-mma-f16-instance-ncols1_8-ncols2_8.cu fattn-tile-instance-dkq112-dv112.cu fattn-tile-instance-dkq128-dv128.cu fattn-tile-instance-dkq256-dv256.cu fattn-tile-instance-dkq40-dv40.cu fattn-tile-instance-dkq576-dv512.cu fattn-tile-instance-dkq64-dv64.cu fattn-tile-instance-dkq72-dv72.cu fattn-tile-instance-dkq80-dv80.cu fattn-tile-instance-dkq96-dv96.cu fattn-vec-instance-f16-f16.cu fattn-vec-instance-f16-q4_0.cu fattn-vec-instance-f16-q4_1.cu fattn-vec-instance-f16-q5_0.cu fattn-vec-instance-f16-q5_1.cu fattn-vec-instance-f16-q8_0.cu fattn-vec-instance-q4_0-f16.cu fattn-vec-instance-q4_0-q4_0.cu fattn-vec-instance-q4_0-q4_1.cu fattn-vec-instance-q4_0-q5_0.cu fattn-vec-instance-q4_0-q5_1.cu fattn-vec-instance-q4_0-q8_0.cu fattn-vec-instance-q4_1-f16.cu fattn-vec-instance-q4_1-q4_0.cu fattn-vec-instance-q4_1-q4_1.cu fattn-vec-instance-q4_1-q5_0.cu fattn-vec-instance-q4_1-q5_1.cu fattn-vec-instance-q4_1-q8_0.cu fattn-vec-instance-q5_0-f16.cu fattn-vec-instance-q5_0-q4_0.cu fattn-vec-instance-q5_0-q4_1.cu fattn-vec-instance-q5_0-q5_0.cu fattn-vec-instance-q5_0-q5_1.cu fattn-vec-instance-q5_0-q8_0.cu fattn-vec-instance-q5_1-f16.cu fattn-vec-instance-q5_1-q4_0.cu fattn-vec-instance-q5_1-q4_1.cu fattn-vec-instance-q5_1-q5_0.cu fattn-vec-instance-q5_1-q5_1.cu fattn-vec-instance-q5_1-q8_0.cu fattn-vec-instance-q8_0-f16.cu fattn-vec-instance-q8_0-q4_0.cu fattn-vec-instance-q8_0-q4_1.cu fattn-vec-instance-q8_0-q5_0.cu fattn-vec-instance-q8_0-q5_1.cu fattn-vec-instance-q8_0-q8_0.cu generate_cu_files.py mmf-instance-ncols_1.cu mmf-instance-ncols_10.cu mmf-instance-ncols_11.cu mmf-instance-ncols_12.cu mmf-instance-ncols_13.cu mmf-instance-ncols_14.cu mmf-instance-ncols_15.cu mmf-instance-ncols_16.cu mmf-instance-ncols_2.cu mmf-instance-ncols_3.cu mmf-instance-ncols_4.cu mmf-instance-ncols_5.cu mmf-instance-ncols_6.cu mmf-instance-ncols_7.cu mmf-instance-ncols_8.cu mmf-instance-ncols_9.cu mmq-instance-iq1_s.cu mmq-instance-iq2_s.cu mmq-instance-iq2_xs.cu mmq-instance-iq2_xxs.cu mmq-instance-iq3_s.cu mmq-instance-iq3_xxs.cu mmq-instance-iq4_nl.cu mmq-instance-iq4_xs.cu mmq-instance-mxfp4.cu mmq-instance-q2_k.cu mmq-instance-q3_k.cu mmq-instance-q4_0.cu mmq-instance-q4_1.cu mmq-instance-q4_k.cu mmq-instance-q5_0.cu mmq-instance-q5_1.cu mmq-instance-q5_k.cu mmq-instance-q6_k.cu mmq-instance-q8_0.cuggml-hexagon
htp
CMakeLists.txt act-ops.c argsort-ops.c binary-ops.c cmake-toolchain.cmake cpy-ops.c flash-attn-ops.c get-rows-ops.c hex-dma.c hex-dma.h hex-dump.h hex-fastdiv.h hex-utils.h htp-ctx.h htp-msg.h htp-ops.h htp_iface.idl hvx-arith.h hvx-base.h hvx-copy.h hvx-div.h hvx-dump.h hvx-exp.h hvx-floor.h hvx-inverse.h hvx-reduce.h hvx-scale.h hvx-sigmoid.h hvx-sqrt.h hvx-types.h hvx-utils.h main.c matmul-ops.c rope-ops.c set-rows-ops.c softmax-ops.c sum-rows-ops.c unary-ops.c worker-pool.c worker-pool.hggml-metal
CMakeLists.txt ggml-metal-common.cpp ggml-metal-common.h ggml-metal-context.h ggml-metal-context.m ggml-metal-device.cpp ggml-metal-device.h ggml-metal-device.m ggml-metal-impl.h ggml-metal-ops.cpp ggml-metal-ops.h ggml-metal.cpp ggml-metal.metalggml-opencl
kernels
add.cl add_id.cl argsort.cl clamp.cl concat.cl conv2d.cl conv2d_f16_f32.cl cpy.cl cvt.cl diag_mask_inf.cl div.cl embed_kernel.py expm1.cl fill.cl flash_attn_f16.cl flash_attn_f32.cl flash_attn_f32_f16.cl gelu.cl gemm_moe_mxfp4_f32.cl gemv_moe_mxfp4_f32.cl gemv_noshuffle.cl gemv_noshuffle_general.cl gemv_noshuffle_general_q8_0_f32.cl get_rows.cl glu.cl group_norm.cl im2col_f16.cl im2col_f32.cl mean.cl mul.cl mul_mat_Ab_Bi_8x4.cl mul_mat_f16_f32.cl mul_mm_f16_f32_kq_kqv.cl mul_mm_f16_f32_l4_lm.cl mul_mm_f32_f32_l4_lm.cl mul_mm_q6_k_f32_l4_lm.cl mul_mm_q8_0_f32_8x4.cl mul_mm_q8_0_f32_l4_lm.cl mul_mv_f16_f16.cl mul_mv_f16_f32.cl mul_mv_f16_f32_1row.cl mul_mv_f16_f32_l4.cl mul_mv_f32_f32.cl mul_mv_id_mxfp4_f32.cl mul_mv_id_mxfp4_f32_flat.cl mul_mv_id_q4_0_f32_8x_flat.cl mul_mv_id_q8_0_f32.cl mul_mv_id_q8_0_f32_flat.cl mul_mv_mxfp4_f32.cl mul_mv_mxfp4_f32_flat.cl mul_mv_q4_0_f32.cl mul_mv_q4_0_f32_1d_16x_flat.cl mul_mv_q4_0_f32_1d_8x_flat.cl mul_mv_q4_0_f32_8x_flat.cl mul_mv_q4_0_f32_v.cl mul_mv_q4_k_f32.cl mul_mv_q6_k_f32.cl mul_mv_q6_k_f32_flat.cl mul_mv_q8_0_f32.cl mul_mv_q8_0_f32_flat.cl norm.cl pad.cl relu.cl repeat.cl rms_norm.cl rope.cl scale.cl set_rows.cl sigmoid.cl silu.cl softmax_4_f16.cl softmax_4_f32.cl softmax_f16.cl softmax_f32.cl softplus.cl solve_tri.cl sqr.cl sqrt.cl ssm_conv.cl sub.cl sum_rows.cl tanh.cl transpose.cl tri.cl tsembd.cl upscale.clggml-sycl
CMakeLists.txt add-id.cpp add-id.hpp backend.hpp binbcast.cpp binbcast.hpp common.cpp common.hpp concat.cpp concat.hpp conv.cpp conv.hpp convert.cpp convert.hpp count-equal.cpp count-equal.hpp cpy.cpp cpy.hpp dequantize.hpp dmmv.cpp dmmv.hpp element_wise.cpp element_wise.hpp gemm.hpp getrows.cpp getrows.hpp ggml-sycl.cpp gla.cpp gla.hpp im2col.cpp im2col.hpp mmq.cpp mmq.hpp mmvq.cpp mmvq.hpp norm.cpp norm.hpp outprod.cpp outprod.hpp pad.cpp pad.hpp pad_reflect_1d.cpp pad_reflect_1d.hpp presets.hpp quantize.hpp quants.hpp repeat_back.cpp repeat_back.hpp roll.cpp roll.hpp rope.cpp rope.hpp set.cpp set.hpp set_rows.cpp set_rows.hpp softmax.cpp softmax.hpp ssm_conv.cpp ssm_conv.hpp sycl_hw.cpp sycl_hw.hpp tsembd.cpp tsembd.hpp vecdotq.hpp wkv.cpp wkv.hppggml-virtgpu
backend
CMakeLists.txt apir_cs_ggml-rpc-back.cpp backend-convert.h backend-dispatched-backend.cpp backend-dispatched-buffer-type.cpp backend-dispatched-buffer.cpp backend-dispatched-device.cpp backend-dispatched.cpp backend-dispatched.gen.h backend-dispatched.h backend-virgl-apir.h backend.cppggml-vulkan
vulkan-shaders
CMakeLists.txt abs.comp acc.comp add.comp add1.comp add_id.comp arange.comp argmax.comp argsort.comp argsort_large.comp ceil.comp clamp.comp concat.comp contig_copy.comp conv2d_dw.comp conv2d_mm.comp conv_transpose_1d.comp copy.comp copy_from_quant.comp copy_to_quant.comp copy_transpose.comp cos.comp count_equal.comp count_experts.comp cumsum.comp cumsum_multipass1.comp cumsum_multipass2.comp dequant_f32.comp dequant_funcs.glsl dequant_funcs_cm2.glsl dequant_head.glsl dequant_iq1_m.comp dequant_iq1_s.comp dequant_iq2_s.comp dequant_iq2_xs.comp dequant_iq2_xxs.comp dequant_iq3_s.comp dequant_iq3_xxs.comp dequant_iq4_nl.comp dequant_iq4_xs.comp dequant_mxfp4.comp dequant_q2_k.comp dequant_q3_k.comp dequant_q4_0.comp dequant_q4_1.comp dequant_q4_k.comp dequant_q5_0.comp dequant_q5_1.comp dequant_q5_k.comp dequant_q6_k.comp dequant_q8_0.comp diag.comp diag_mask_inf.comp div.comp exp.comp fill.comp flash_attn.comp flash_attn_base.glsl flash_attn_cm1.comp flash_attn_cm2.comp flash_attn_mask_opt.comp flash_attn_split_k_reduce.comp floor.comp geglu.comp geglu_erf.comp geglu_quick.comp gelu.comp gelu_erf.comp gelu_quick.comp generic_binary_head.glsl generic_head.glsl generic_unary_head.glsl get_rows.comp get_rows_quant.comp glu_head.glsl glu_main.glsl group_norm.comp hardsigmoid.comp hardswish.comp im2col.comp im2col_3d.comp l2_norm.comp leaky_relu.comp log.comp mul.comp mul_mat_split_k_reduce.comp mul_mat_vec.comp mul_mat_vec_base.glsl mul_mat_vec_iface.glsl mul_mat_vec_iq1_m.comp mul_mat_vec_iq1_s.comp mul_mat_vec_iq2_s.comp mul_mat_vec_iq2_xs.comp mul_mat_vec_iq2_xxs.comp mul_mat_vec_iq3_s.comp mul_mat_vec_iq3_xxs.comp mul_mat_vec_nc.comp mul_mat_vec_p021.comp mul_mat_vec_q2_k.comp mul_mat_vec_q3_k.comp mul_mat_vec_q4_k.comp mul_mat_vec_q5_k.comp mul_mat_vec_q6_k.comp mul_mat_vecq.comp mul_mat_vecq_funcs.glsl mul_mm.comp mul_mm_cm2.comp mul_mm_funcs.glsl mul_mm_id_funcs.glsl mul_mmq.comp mul_mmq_funcs.glsl mul_mmq_shmem_types.glsl multi_add.comp neg.comp norm.comp opt_step_adamw.comp opt_step_sgd.comp pad.comp pool2d.comp quantize_q8_1.comp reglu.comp relu.comp repeat.comp repeat_back.comp rms_norm.comp rms_norm_back.comp rms_norm_partials.comp roll.comp rope_funcs.glsl rope_head.glsl rope_multi.comp rope_neox.comp rope_norm.comp rope_params.glsl rope_vision.comp round.comp rte.glsl scale.comp sigmoid.comp silu.comp silu_back.comp sin.comp soft_max.comp soft_max_back.comp soft_max_large1.comp soft_max_large2.comp soft_max_large3.comp soft_max_large_common.glsl softplus.comp solve_tri.comp sqrt.comp square.comp ssm_conv.comp ssm_scan.comp step.comp sub.comp sum_rows.comp sum_rows.glsl swiglu.comp swiglu_oai.comp tanh.comp timestep_embedding.comp topk_argsort.comp topk_moe.comp topk_nary_search.comp tri.comp trunc.comp types.glsl upscale.comp utils.glsl vulkan-shaders-gen.cpp wkv6.comp wkv7.comp xielu.compggml-webgpu
wgsl-shaders
argmax.wgsl argsort.wgsl argsort_merge.wgsl binary.wgsl common_decls.tmpl cpy.tmpl.wgsl cumsum.wgsl embed_wgsl.py flash_attn.wgsl get_rows.tmpl.wgsl glu.tmpl.wgsl memset.wgsl mul_mat.tmpl.wgsl mul_mat_decls.tmpl mul_mat_reg_tile.tmpl.wgsl mul_mat_subgroup_matrix.tmpl.wgsl mul_mat_vec.tmpl.wgsl pad.wgsl rms_norm.wgsl rope.tmpl.wgsl scale.tmpl.wgsl set_rows.wgsl soft_max.tmpl.wgsl sum_rows.wgsl unary.wgslgguf-py
gguf
scripts
gguf_convert_endian.py gguf_dump.py gguf_editor_gui.py gguf_hash.py gguf_new_metadata.py gguf_set_metadata.pygrammars
README.md arithmetic.gbnf c.gbnf chess.gbnf english.gbnf japanese.gbnf json.gbnf json_arr.gbnf list.gbnfmedia
llama0-banner.png llama0-logo.png llama1-banner.png llama1-icon-transparent.png llama1-icon-transparent.svg llama1-icon.png llama1-icon.svg llama1-logo.png llama1-logo.svg matmul.png matmul.svgmodels
templates
Apertus-8B-Instruct.jinja ByteDance-Seed-OSS.jinja CohereForAI-c4ai-command-r-plus-tool_use.jinja CohereForAI-c4ai-command-r7b-12-2024-tool_use.jinja GLM-4.6.jinja Kimi-K2-Instruct.jinja Kimi-K2-Thinking.jinja MiMo-VL.jinja MiniMax-M2.jinja Mistral-Small-3.2-24B-Instruct-2506.jinja NVIDIA-Nemotron-3-Nano-30B-A3B-BF16.jinja NVIDIA-Nemotron-Nano-v2.jinja NousResearch-Hermes-2-Pro-Llama-3-8B-tool_use.jinja NousResearch-Hermes-3-Llama-3.1-8B-tool_use.jinja Qwen-QwQ-32B.jinja Qwen-Qwen2.5-7B-Instruct.jinja Qwen-Qwen3-0.6B.jinja Qwen3-Coder.jinja README.md deepseek-ai-DeepSeek-R1-Distill-Llama-8B.jinja deepseek-ai-DeepSeek-R1-Distill-Qwen-32B.jinja deepseek-ai-DeepSeek-V3.1.jinja fireworks-ai-llama-3-firefunction-v2.jinja google-gemma-2-2b-it.jinja ibm-granite-granite-3.3-2B-Instruct.jinja llama-cpp-deepseek-r1.jinja llama-cpp-lfm2.jinja llama-cpp-rwkv-world.jinja meetkai-functionary-medium-v3.1.jinja meetkai-functionary-medium-v3.2.jinja meta-llama-Llama-3.1-8B-Instruct.jinja meta-llama-Llama-3.2-3B-Instruct.jinja meta-llama-Llama-3.3-70B-Instruct.jinja microsoft-Phi-3.5-mini-instruct.jinja mistralai-Ministral-3-14B-Reasoning-2512.jinja mistralai-Mistral-Nemo-Instruct-2407.jinja moonshotai-Kimi-K2.jinja openai-gpt-oss-120b.jinja unsloth-Apriel-1.5.jinja unsloth-mistral-Devstral-Small-2507.jinja upstage-Solar-Open-100B.jinjarequirements
requirements-all.txt requirements-compare-llama-bench.txt requirements-convert_hf_to_gguf.txt requirements-convert_hf_to_gguf_update.txt requirements-convert_legacy_llama.txt requirements-convert_llama_ggml_to_gguf.txt requirements-convert_lora_to_gguf.txt requirements-gguf_editor_gui.txt requirements-pydantic.txt requirements-server-bench.txt requirements-test-tokenizer-random.txt requirements-tool_bench.txtscripts
bench-models.sh build-info.sh check-requirements.sh compare-commits.sh compare-llama-bench.py compare-logprobs.py create_ops_docs.py debug-test.sh fetch_server_test_models.py gen-authors.sh gen-unicode-data.py get-flags.mk get-hellaswag.sh get-pg.sh get-wikitext-103.sh get-wikitext-2.sh get-winogrande.sh get_chat_template.py hf.sh install-oneapi.bat pr2wt.sh serve-static.js server-bench.py sync-ggml-am.sh sync-ggml.last sync-ggml.sh sync_vendor.py tool_bench.py tool_bench.sh verify-checksum-models.py xxd.cmakesrc
models
afmoe.cpp apertus.cpp arcee.cpp arctic.cpp arwkv7.cpp baichuan.cpp bailingmoe.cpp bailingmoe2.cpp bert.cpp bitnet.cpp bloom.cpp chameleon.cpp chatglm.cpp codeshell.cpp cogvlm.cpp cohere2-iswa.cpp command-r.cpp dbrx.cpp deci.cpp deepseek.cpp deepseek2.cpp dots1.cpp dream.cpp ernie4-5-moe.cpp ernie4-5.cpp exaone-moe.cpp exaone.cpp exaone4.cpp falcon-h1.cpp falcon.cpp gemma-embedding.cpp gemma.cpp gemma2-iswa.cpp gemma3.cpp gemma3n-iswa.cpp glm4-moe.cpp glm4.cpp gpt2.cpp gptneox.cpp granite-hybrid.cpp granite.cpp graph-context-mamba.cpp grok.cpp grovemoe.cpp hunyuan-dense.cpp hunyuan-moe.cpp internlm2.cpp jais.cpp jamba.cpp kimi-linear.cpp lfm2.cpp llada-moe.cpp llada.cpp llama-iswa.cpp llama.cpp maincoder.cpp mamba.cpp mimo2-iswa.cpp minicpm3.cpp minimax-m2.cpp mistral3.cpp models.h modern-bert.cpp mpt.cpp nemotron-h.cpp nemotron.cpp neo-bert.cpp olmo.cpp olmo2.cpp olmoe.cpp openai-moe-iswa.cpp openelm.cpp orion.cpp pangu-embedded.cpp phi2.cpp phi3.cpp plamo.cpp plamo2.cpp plamo3.cpp plm.cpp qwen.cpp qwen2.cpp qwen2moe.cpp qwen2vl.cpp qwen3.cpp qwen35.cpp qwen35moe.cpp qwen3moe.cpp qwen3next.cpp qwen3vl-moe.cpp qwen3vl.cpp refact.cpp rnd1.cpp rwkv6-base.cpp rwkv6.cpp rwkv6qwen2.cpp rwkv7-base.cpp rwkv7.cpp seed-oss.cpp smallthinker.cpp smollm3.cpp stablelm.cpp starcoder.cpp starcoder2.cpp step35-iswa.cpp t5-dec.cpp t5-enc.cpp wavtokenizer-dec.cpp xverse.cpptests
peg-parser
simple-tokenize.cpp simple-tokenize.h test-basic.cpp test-gbnf-generation.cpp test-json-parser.cpp test-json-serialization.cpp test-unicode.cpp tests.htools
cvector-generator
CMakeLists.txt README.md completions.txt cvector-generator.cpp mean.hpp negative.txt pca.hpp positive.txtmtmd
legacy-models
convert_image_encoder_to_gguf.py glmedge-convert-image-encoder-to-gguf.py glmedge-surgery.py llava_surgery.py llava_surgery_v2.py minicpmv-convert-image-encoder-to-gguf.py minicpmv-surgery.pymodels
cogvlm.cpp conformer.cpp glm4v.cpp internvl.cpp kimik25.cpp kimivl.cpp llama4.cpp llava.cpp minicpmv.cpp mobilenetv5.cpp models.h pixtral.cpp qwen2vl.cpp qwen3vl.cpp siglip.cpp whisper-enc.cpp youtuvl.cppserver
public_legacy
colorthemes.css completion.js favicon.ico index-new.html index.html index.js json-schema-to-grammar.mjs loading.html prompt-formats.js style.css system-prompts.js theme-beeninorder.css theme-ketivah.css theme-mangotango.css theme-playground.css theme-polarnight.css theme-snowstorm.csspublic_simplechat
datautils.mjs index.html readme.md simplechat.css simplechat.js simplechat_screens.webp ui.mjstests
unit
test_basic.py test_chat_completion.py test_compat_anthropic.py test_compat_oai_responses.py test_completion.py test_ctx_shift.py test_embedding.py test_infill.py test_lora.py test_rerank.py test_router.py test_security.py test_sleep.py test_slot_save.py test_speculative.py test_template.py test_tokenize.py test_tool_call.py test_vision_api.pywebui
.storybook
ModeWatcherDecorator.svelte TooltipProviderDecorator.svelte main.ts preview.ts vitest.setup.tssrc
lib
components
app
chat
ChatAttachments
ChatAttachmentPreview.svelte ChatAttachmentThumbnailFile.svelte ChatAttachmentThumbnailImage.svelte ChatAttachmentsList.svelte ChatAttachmentsViewAll.svelteChatForm
ChatFormActions
ChatFormActionFileAttachments.svelte ChatFormActionRecord.svelte ChatFormActionSubmit.svelte ChatFormActions.svelteChatMessages
ChatMessage.svelte ChatMessageActions.svelte ChatMessageAssistant.svelte ChatMessageBranchingControls.svelte ChatMessageEditForm.svelte ChatMessageStatistics.svelte ChatMessageSystem.svelte ChatMessageThinkingBlock.svelte ChatMessageUser.svelte ChatMessages.svelteChatScreen
ChatScreen.svelte ChatScreenDragOverlay.svelte ChatScreenHeader.svelte ChatScreenProcessingInfo.sveltedialogs
DialogChatAttachmentPreview.svelte DialogChatAttachmentsViewAll.svelte DialogChatError.svelte DialogChatSettings.svelte DialogConfirmation.svelte DialogConversationSelection.svelte DialogConversationTitleUpdate.svelte DialogEmptyFileAlert.svelte DialogModelInformation.svelte DialogModelNotAvailable.sveltemisc
ActionButton.svelte ActionDropdown.svelte BadgeChatStatistic.svelte BadgeInfo.svelte BadgeModality.svelte CodePreviewDialog.svelte ConversationSelection.svelte CopyToClipboardIcon.svelte KeyboardShortcutInfo.svelte MarkdownContent.svelte RemoveButton.svelte SearchInput.svelte SyntaxHighlightedCode.svelteui
alert-dialog
alert-dialog-action.svelte alert-dialog-cancel.svelte alert-dialog-content.svelte alert-dialog-description.svelte alert-dialog-footer.svelte alert-dialog-header.svelte alert-dialog-overlay.svelte alert-dialog-title.svelte alert-dialog-trigger.svelte index.tscard
card-action.svelte card-content.svelte card-description.svelte card-footer.svelte card-header.svelte card-title.svelte card.svelte index.tsdialog
dialog-close.svelte dialog-content.svelte dialog-description.svelte dialog-footer.svelte dialog-header.svelte dialog-overlay.svelte dialog-title.svelte dialog-trigger.svelte index.tsdropdown-menu
dropdown-menu-checkbox-item.svelte dropdown-menu-content.svelte dropdown-menu-group-heading.svelte dropdown-menu-group.svelte dropdown-menu-item.svelte dropdown-menu-label.svelte dropdown-menu-radio-group.svelte dropdown-menu-radio-item.svelte dropdown-menu-separator.svelte dropdown-menu-shortcut.svelte dropdown-menu-sub-content.svelte dropdown-menu-sub-trigger.svelte dropdown-menu-trigger.svelte index.tspopover
index.ts popover-close.svelte popover-content.svelte popover-portal.svelte popover-trigger.svelte popover.svelteselect
index.ts select-content.svelte select-group-heading.svelte select-group.svelte select-item.svelte select-label.svelte select-scroll-down-button.svelte select-scroll-up-button.svelte select-separator.svelte select-trigger.sveltesheet
index.ts sheet-close.svelte sheet-content.svelte sheet-description.svelte sheet-footer.svelte sheet-header.svelte sheet-overlay.svelte sheet-title.svelte sheet-trigger.sveltesidebar
constants.ts context.svelte.ts index.ts sidebar-content.svelte sidebar-footer.svelte sidebar-group-action.svelte sidebar-group-content.svelte sidebar-group-label.svelte sidebar-group.svelte sidebar-header.svelte sidebar-input.svelte sidebar-inset.svelte sidebar-menu-action.svelte sidebar-menu-badge.svelte sidebar-menu-button.svelte sidebar-menu-item.svelte sidebar-menu-skeleton.svelte sidebar-menu-sub-button.svelte sidebar-menu-sub-item.svelte sidebar-menu-sub.svelte sidebar-menu.svelte sidebar-provider.svelte sidebar-rail.svelte sidebar-separator.svelte sidebar-trigger.svelte sidebar.sveltetable
index.ts table-body.svelte table-caption.svelte table-cell.svelte table-footer.svelte table-head.svelte table-header.svelte table-row.svelte table.svelteconstants
auto-scroll.ts binary-detection.ts default-context.ts floating-ui-constraints.ts icons.ts input-classes.ts latex-protection.ts literal-html.ts localstorage-keys.ts max-bundle-size.ts precision.ts processing-info.ts settings-config.ts supported-file-types.ts table-html-restorer.ts tooltip-config.ts viewport.tsstores
chat.svelte.ts conversations.svelte.ts models.svelte.ts persisted.svelte.ts server.svelte.ts settings.svelte.tsutils
api-headers.ts api-key-validation.ts attachment-display.ts attachment-type.ts audio-recording.ts autoresize-textarea.ts branching.ts browser-only.ts clipboard.ts config-helpers.ts conversation-utils.ts convert-files-to-extra.ts file-preview.ts file-type.ts formatters.ts index.ts is-ime-composing.ts latex-protection.ts modality-file-validation.ts model-names.ts pdf-processing.ts portal-to-body.ts precision.ts process-uploaded-files.ts svg-to-png.ts syntax-highlight-language.ts text-files.ts text.ts webp-to-png.tstests
llama.cpp/tools/server/public_legacy/index-new.html
raw
1<!DOCTYPE html>
2
3<html>
4
5<head>
6 <meta charset="UTF-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
8 <meta name="color-scheme" content="light dark">
9 <title>llama.cpp - chat</title>
10
11 <link rel="icon" type="image/x-icon" href="favicon.ico">
12 <link rel="stylesheet" href="style.css">
13
14 <script type="module">
15 import {
16 html, h, signal, effect, computed, render, useSignal, useEffect, useRef, Component
17 } from './index.js';
18
19 import { llama } from './completion.js';
20 import { SchemaConverter } from './json-schema-to-grammar.mjs';
21 import { promptFormats } from './prompt-formats.js';
22 import { systemPrompts } from './system-prompts.js'; // multilingual is wip
23 let selected_image = false;
24 var slot_id = -1;
25
26 const session = signal({
27 prompt: "",
28 template: "{{prompt}}\n{{history}}{{char}}",
29 historyTemplate: "{{name}}: {{message}}\n",
30 transcript: [],
31 type: "chat", // "chat" | "completion"
32 char: "ASSISTANT",
33 user: "USER",
34 image_selected: ''
35 })
36
37 const params = signal({
38 n_predict: 358, // 358 is a nice number
39 temperature: 0.8, // adapt all following parameters to optimized min-p requierements. If for non-english, set to 0.6 or lower
40 repeat_last_n: 0, // 0 = disable penalty, -1 = context size
41 repeat_penalty: 1.0, // 1.0 = disabled
42 dry_multiplier: 0.0, // 0.0 = disabled, 0.8 works well
43 dry_base: 1.75, // 0.0 = disabled
44 dry_allowed_length: 2, // tokens extending repetitions beyond this receive penalty, 2 works well
45 dry_penalty_last_n: -1, // how many tokens to scan for repetitions (0 = disable penalty, -1 = context size)
46 top_k: 0, // <= 0 to use vocab size
47 top_p: 1.0, // 1.0 = disabled
48 min_p: 0.05, // 0 = disabled; recommended for non-english: ~ 0.4
49 xtc_probability: 0.0, // 0 = disabled;
50 xtc_threshold: 0.1, // > 0.5 disables XTC;
51 typical_p: 1.0, // 1.0 = disabled
52 presence_penalty: 0.0, // 0.0 = disabled
53 frequency_penalty: 0.0, // 0.0 = disabled
54 mirostat: 0, // 0/1/2
55 mirostat_tau: 5, // target entropy
56 mirostat_eta: 0.1, // learning rate
57 grammar: '',
58 n_probs: 0, // no completion_probabilities,
59 min_keep: 0, // min probs from each sampler,
60 image_data: [],
61 cache_prompt: true,
62 api_key: ''
63 })
64
65
66
67 /* START: Support for storing prompt templates and parameters in browser's LocalStorage */
68
69 const local_storage_storageKey = "llamacpp_server_local_storage";
70
71 function local_storage_setDataFromObject(tag, content) {
72 localStorage.setItem(local_storage_storageKey + '/' + tag, JSON.stringify(content));
73 }
74
75 function local_storage_setDataFromRawText(tag, content) {
76 localStorage.setItem(local_storage_storageKey + '/' + tag, content);
77 }
78
79 function local_storage_getDataAsObject(tag) {
80 const item = localStorage.getItem(local_storage_storageKey + '/' + tag);
81 if (!item) {
82 return null;
83 } else {
84 return JSON.parse(item);
85 }
86 }
87
88 function local_storage_getDataAsRawText(tag) {
89 const item = localStorage.getItem(local_storage_storageKey + '/' + tag);
90 if (!item) {
91 return null;
92 } else {
93 return item;
94 }
95 }
96
97 // create a container for user templates and settings
98
99 const savedUserTemplates = signal({})
100 const selectedUserTemplate = signal({ name: '', template: { session: {}, params: {} } })
101
102 // let's import locally saved templates and settings if there are any
103 // user templates and settings are stored in one object
104 // in form of { "templatename": "templatedata" } and { "settingstemplatename":"settingsdata" }
105
106 console.log('Importing saved templates')
107
108 let importedTemplates = local_storage_getDataAsObject('user_templates')
109
110 if (importedTemplates) {
111 // saved templates were successfuly imported.
112
113 console.log('Processing saved templates and updating default template')
114 params.value = { ...params.value, image_data: [] };
115
116 //console.log(importedTemplates);
117 savedUserTemplates.value = importedTemplates;
118
119 //override default template
120 savedUserTemplates.value.default = { session: session.value, params: params.value }
121 local_storage_setDataFromObject('user_templates', savedUserTemplates.value)
122 } else {
123 // no saved templates detected.
124
125 console.log('Initializing LocalStorage and saving default template')
126
127 savedUserTemplates.value = { "default": { session: session.value, params: params.value } }
128 local_storage_setDataFromObject('user_templates', savedUserTemplates.value)
129 }
130
131 function userTemplateResetToDefault() {
132 console.log('Reseting themplate to default')
133 selectedUserTemplate.value.name = 'default';
134 selectedUserTemplate.value.data = savedUserTemplates.value['default'];
135 }
136
137 function userTemplateApply(t) {
138 session.value = t.data.session;
139 session.value = { ...session.value, image_selected: '' };
140 params.value = t.data.params;
141 params.value = { ...params.value, image_data: [] };
142 }
143
144 function userTemplateResetToDefaultAndApply() {
145 userTemplateResetToDefault()
146 userTemplateApply(selectedUserTemplate.value)
147 }
148
149 function userTemplateLoadAndApplyAutosaved() {
150 // get autosaved last used template
151 let lastUsedTemplate = local_storage_getDataAsObject('user_templates_last')
152
153 if (lastUsedTemplate) {
154
155 console.log('Autosaved template found, restoring')
156
157 selectedUserTemplate.value = lastUsedTemplate
158 }
159 else {
160
161 console.log('No autosaved template found, using default template')
162 // no autosaved last used template was found, so load from default.
163
164 userTemplateResetToDefault()
165 }
166
167 console.log('Applying template')
168 // and update internal data from templates
169
170 userTemplateApply(selectedUserTemplate.value)
171 }
172
173 //console.log(savedUserTemplates.value)
174 //console.log(selectedUserTemplate.value)
175
176 function userTemplateAutosave() {
177 console.log('Template Autosave...')
178 if (selectedUserTemplate.value.name == 'default') {
179 // we don't want to save over default template, so let's create a new one
180 let newTemplateName = 'UserTemplate-' + Date.now().toString()
181 let newTemplate = { 'name': newTemplateName, 'data': { 'session': session.value, 'params': params.value } }
182
183 console.log('Saving as ' + newTemplateName)
184
185 // save in the autosave slot
186 local_storage_setDataFromObject('user_templates_last', newTemplate)
187
188 // and load it back and apply
189 userTemplateLoadAndApplyAutosaved()
190 } else {
191 local_storage_setDataFromObject('user_templates_last', { 'name': selectedUserTemplate.value.name, 'data': { 'session': session.value, 'params': params.value } })
192 }
193 }
194
195 console.log('Checking for autosaved last used template')
196 userTemplateLoadAndApplyAutosaved()
197
198 /* END: Support for storing prompt templates and parameters in browser's LocalStorage */
199
200 const llamaStats = signal(null)
201 const controller = signal(null)
202
203 // currently generating a completion?
204 const generating = computed(() => controller.value != null)
205
206 // has the user started a chat?
207 const chatStarted = computed(() => session.value.transcript.length > 0)
208
209 const transcriptUpdate = (transcript) => {
210 session.value = {
211 ...session.value,
212 transcript
213 }
214 }
215
216 // simple template replace
217 const template = (str, extraSettings) => {
218 let settings = session.value;
219 if (extraSettings) {
220 settings = { ...settings, ...extraSettings };
221 }
222 return String(str).replaceAll(/\{\{(.*?)\}\}/g, (_, key) => template(settings[key]));
223 }
224
225 async function runLlama(prompt, llamaParams, char) {
226 const currentMessages = [];
227 const history = session.value.transcript;
228 if (controller.value) {
229 throw new Error("already running");
230 }
231 controller.value = new AbortController();
232 for await (const chunk of llama(prompt, llamaParams, { controller: controller.value, api_url: new URL('.', document.baseURI).href })) {
233 const data = chunk.data;
234 if (data.stop) {
235 while (
236 currentMessages.length > 0 &&
237 currentMessages[currentMessages.length - 1].content.match(/\n$/) != null
238 ) {
239 currentMessages.pop();
240 }
241 transcriptUpdate([...history, [char, currentMessages]])
242 console.log("Completion finished: '", currentMessages.map(msg => msg.content).join(''), "', summary: ", data);
243 } else {
244 currentMessages.push(data);
245 slot_id = data.slot_id;
246 if (selected_image && !data.multimodal) {
247 alert("The server was not compiled for multimodal or the model projector can't be loaded."); return;
248 }
249 transcriptUpdate([...history, [char, currentMessages]])
250 }
251 if (data.timings) {
252 // llamaStats.value = data.timings;
253 llamaStats.value = data;
254 }
255 }
256 controller.value = null;
257 }
258
259 // send message to server
260 const chat = async (msg) => {
261 if (controller.value) {
262 console.log('already running...');
263 return;
264 }
265 // just in case (e.g. llama2)
266 const suffix = session.value.userMsgSuffix || "";
267 const prefix = session.value.userMsgPrefix || "";
268 const userMsg = prefix + msg + suffix;
269
270 transcriptUpdate([...session.value.transcript, ["{{user}}", userMsg]])
271
272 let prompt = template(session.value.template, {
273 message: msg,
274 history: session.value.transcript.flatMap(
275 ([name, data]) =>
276 template(
277 session.value.historyTemplate,
278 {
279 name,
280 message: Array.isArray(data) ?
281 data.map(msg => msg.content).join('').replace(/^\s/, '') :
282 data,
283 }
284 )
285 ).join(''),
286 });
287 if (selected_image) {
288 prompt = `A chat between a curious human and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the human's questions.\nUSER:[img-10]${msg}\nASSISTANT:`;
289 }
290 await runLlama(prompt, {
291 ...params.value,
292 slot_id: slot_id,
293 stop: ["</s>", "<|end|>", "<|eot_id|>", "<|end_of_text|>", "<|im_end|>", "<|EOT|>", "<|END_OF_TURN_TOKEN|>", "<|end_of_turn|>", "<|endoftext|>", template("{{char}}"), template("{{user}}")],
294 }, "{{char}}");
295 }
296
297 const runCompletion = () => {
298 if (controller.value) {
299 console.log('already running...');
300 return;
301 }
302 const { prompt } = session.value;
303 transcriptUpdate([...session.value.transcript, ["", prompt]]);
304 runLlama(prompt, {
305 ...params.value,
306 slot_id: slot_id,
307 stop: [],
308 }, "").finally(() => {
309 session.value.prompt = session.value.transcript.map(([_, data]) =>
310 Array.isArray(data) ? data.map(msg => msg.content).join('') : data
311 ).join('');
312 session.value.transcript = [];
313 })
314 }
315
316 const stop = (e) => {
317 e.preventDefault();
318 if (controller.value) {
319 controller.value.abort();
320 controller.value = null;
321 }
322 }
323
324 const reset = (e) => {
325 stop(e);
326 transcriptUpdate([]);
327 }
328
329 const uploadImage = (e) => {
330 e.preventDefault();
331 document.getElementById("fileInput").click();
332 document.getElementById("fileInput").addEventListener("change", function (event) {
333 const selectedFile = event.target.files[0];
334 if (selectedFile) {
335 const reader = new FileReader();
336 reader.onload = function () {
337 const image_data = reader.result;
338 session.value = { ...session.value, image_selected: image_data };
339 params.value = {
340 ...params.value, image_data: [
341 { data: image_data.replace(/data:image\/[^;]+;base64,/, ''), id: 10 }]
342 }
343 };
344 selected_image = true;
345 reader.readAsDataURL(selectedFile);
346 }
347 });
348 }
349
350 function MessageInput() {
351 const message = useSignal("")
352
353 const submit = (e) => {
354 stop(e);
355 chat(message.value);
356 message.value = "";
357 }
358
359 const enterSubmits = (event) => {
360 if (event.which === 13 && !event.shiftKey) {
361 submit(event);
362 }
363 }
364
365 return html`
366 <form onsubmit=${submit}>
367 <div class="chat-input-container">
368 <textarea
369 id="chat-input" placeholder="Say Something ... (Shift + Enter for new line)"
370 class="${generating.value ? 'loading' : null}"
371 oninput=${(e) => message.value = e.target.value}
372 onkeypress=${enterSubmits}
373 rows="2"
374 type="text"
375 value="${message}"
376 ></textarea>
377 </div>
378
379 <div class="right">
380 <button class="button-back" onclick=${reset}>Back</button>
381 <button onclick=${uploadImage}>Upload Image</button>
382 <button onclick=${stop} disabled=${!generating.value}>Stop</button>
383 <button type="submit" disabled=${generating.value}>Submit</button>
384 </div>
385 </form>
386 `
387 }
388
389 // the completion view needs some ux improvements
390 function CompletionControls() {
391 const submit = (e) => {
392 stop(e);
393 runCompletion();
394 }
395 return html`
396 <div class="right">
397 <button onclick=${submit} type="button" disabled=${generating.value}>Start</button>
398 <button onclick=${stop} disabled=${!generating.value}>Stop</button>
399 <button onclick=${reset}>Back</button>
400 </div>`;
401 }
402
403 const ChatLog = (props) => {
404 const messages = session.value.transcript;
405 const container = useRef(null)
406
407 useEffect(() => {
408 // scroll to bottom (if needed)
409 const parent = container.current.parentElement;
410 if (parent && parent.scrollHeight <= parent.scrollTop + parent.offsetHeight + 300) {
411 parent.scrollTo(0, parent.scrollHeight)
412 }
413 }, [messages])
414
415 const isCompletionMode = session.value.type === 'completion'
416 const chatLine = ([user, data], index) => {
417 let message
418 const isArrayMessage = Array.isArray(data)
419 if (params.value.n_probs > 0 && isArrayMessage) {
420 message = html`<${Probabilities} data=${data} />`
421 } else {
422 const text = isArrayMessage ?
423 data.map(msg => msg.content).join('') :
424 data;
425 message = isCompletionMode ?
426 text :
427 html`<${Markdownish} text=${template(text)} />`
428 }
429 if (user) {
430 return html`<p key=${index}><strong class="chat-id-color">${template(user)}</strong> ${message}</p>`
431 } else {
432 return isCompletionMode ?
433 html`<span key=${index}>${message}</span>` :
434 html`<p key=${index}>${message}</p>`
435 }
436 };
437
438 const handleCompletionEdit = (e) => {
439 session.value.prompt = e.target.innerText;
440 session.value.transcript = [];
441 }
442
443 return html`
444 <div id="chat" ref=${container} key=${messages.length}>
445 <img style="width: 60%;${!session.value.image_selected ? `display: none;` : ``}" src="${session.value.image_selected}"/>
446 <span contenteditable=${isCompletionMode} ref=${container} oninput=${handleCompletionEdit}>
447 ${messages.flatMap(chatLine)}
448 </span>
449 </div>`;
450 };
451
452
453
454///////////// UI Improvements /////////////
455//
456//
457const handleToggleChange = (e) => {
458 const isChecked = e.target.checked;
459 session.value = { ...session.value, type: isChecked ? 'completion' : 'chat' };
460 localStorage.setItem('toggleState', isChecked);
461}
462//
463const loadToggleState = () => {
464 const storedState = localStorage.getItem('toggleState');
465 if (storedState !== null) {
466 const isChecked = storedState === 'true';
467 document.getElementById('toggle').checked = isChecked;
468 session.value = { ...session.value, type: isChecked ? 'completion' : 'chat' };
469 }
470}
471//
472document.addEventListener('DOMContentLoaded', loadToggleState);
473//
474//
475// function to update the prompt format
476function updatePromptFormat(e) {
477 const promptFormat = e.target.value;
478 if (promptFormats.hasOwnProperty(promptFormat)) {
479 session.value = {
480 ...session.value,
481 ...promptFormats[promptFormat]
482 };
483 } else {
484 // Use vicuna as llama.cpp's default setting, since it's most common
485 session.value = {
486 ...session.value,
487 template: "{{prompt}}\n{{history}}{{char}}",
488 historyTemplate: "{{name}}: {{message}}\n",
489 char: "ASSISTANT",
490 user: "USER"
491 };
492 }
493 console.log('Updated session value:', session.value);
494}
495//
496//
497// function to update the prompt format from the selected one
498function updatePromptFormatFromDropdown(element) {
499 const promptFormat = element.getAttribute('data-value');
500 console.log('Selected prompt format:', promptFormat); // debugging
501 updatePromptFormat({ target: { value: promptFormat } });
502}
503//
504//
505// function that adds the event listers as soon as the element is available
506function addEventListenersWhenAvailable() {
507 var themeSelector = document.getElementById('theme-selector');
508 if (themeSelector) {
509 themeSelector.addEventListener('change', function(event) {
510 // event-handler-code...
511 });
512 // placeholder event listeners
513 } else {
514 // if the element is not there yet, wait ahead
515 requestAnimationFrame(addEventListenersWhenAvailable);
516 }
517}
518//
519//
520// begin with the check
521requestAnimationFrame(addEventListenersWhenAvailable);
522//
523//
524// avoid default and create new event object with value from data value attribute
525function handleDropdownSelection(e, promptFormat) {
526 e.preventDefault();
527 const customEvent = {
528 target: {
529 value: promptFormat
530 }
531 };
532 // call our updatePromptFormat-function
533 updatePromptFormat(customEvent);
534}
535//
536//
537// function to update the system message
538function updateSystemPrompt(e) {
539 const SystemPrompt = e.target.value;
540 if (systemPrompts.hasOwnProperty(SystemPrompt)) {
541 session.value = {
542 ...session.value,
543 prompt: systemPrompts[SystemPrompt].systemPrompt
544 };
545 }
546}
547//
548//
549///////////// UI Improvements /////////////
550
551
552
553
554const ConfigForm = (props) => {
555 const updateSession = (el) => session.value = { ...session.value, [el.target.name]: el.target.value }
556 const updateParams = (el) => params.value = { ...params.value, [el.target.name]: el.target.value }
557 const updateParamsFloat = (el) => params.value = { ...params.value, [el.target.name]: parseFloat(el.target.value) }
558 const updateParamsInt = (el) => params.value = { ...params.value, [el.target.name]: Math.floor(parseFloat(el.target.value)) }
559 const updateParamsBool = (el) => params.value = { ...params.value, [el.target.name]: el.target.checked }
560
561 const grammarJsonSchemaPropOrder = signal('')
562 const updateGrammarJsonSchemaPropOrder = (el) => grammarJsonSchemaPropOrder.value = el.target.value
563 const convertJSONSchemaGrammar = async () => {
564 try {
565 let schema = JSON.parse(params.value.grammar)
566 const converter = new SchemaConverter({
567 prop_order: grammarJsonSchemaPropOrder.value
568 .split(',')
569 .reduce((acc, cur, i) => ({ ...acc, [cur.trim()]: i }), {}),
570 allow_fetch: true,
571 })
572 schema = await converter.resolveRefs(schema, 'input')
573 converter.visit(schema, '')
574 params.value = {
575 ...params.value,
576 grammar: converter.formatGrammar(),
577 }
578 } catch (e) {
579 alert(`Convert failed: ${e.message}`)
580 }
581 }
582
583 const FloatField = ({ label, title, max, min, name, step, value }) => {
584return html`
585<div>
586 <label for="${name}"><span title="${title}">${label}</span></label>
587 <input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsFloat} title="${title}" />
588 <span id="${name}-value">${value}</span>
589</div>
590`
591};
592
593const IntField = ({ label, title, max, min, step, name, value }) => {
594return html`
595<div>
596 <label for="${name}"><span title="${title}">${label}</span></label>
597 <input type="range" id="${name}" min="${min}" max="${max}" step="${step}" name="${name}" value="${value}" oninput=${updateParamsInt} title="${title}" />
598 <span id="${name}-value">${value}</span>
599</div>
600`
601};
602
603const BoolField = ({ label, title, name, value }) => {
604return html`
605<div>
606 <label for="${name}"><span title="${title}">${label}</span></label>
607 <input type="checkbox" id="${name}" name="${name}" checked="${value}" onclick=${updateParamsBool} title="${title}" />
608</div>
609`
610};
611
612 const userTemplateReset = (e) => {
613 e.preventDefault();
614 userTemplateResetToDefaultAndApply()
615 }
616
617 const UserTemplateResetButton = () => {
618 if (selectedUserTemplate.value.name == 'default') {
619 return html`
620 <button class="reset-button" id="id_reset" onclick="${userTemplateReset}">Reset</button>
621 `
622 }
623
624 return html`
625 <div class="button-container">
626 <button class="reset-button" title="Caution: This resets the entire form." onclick="${userTemplateReset}">Reset</button>
627 </div>
628 `
629 };
630
631 useEffect(() => {
632 // autosave template on every change
633 userTemplateAutosave()
634 }, [session.value, params.value])
635
636 const GrammarControl = () => (
637 html`
638 <div>
639 <div class="grammar">
640 <label for="template"></label>
641 <textarea id="grammar" name="grammar" placeholder="Use GBNF or JSON Schema + Converter" value="${params.value.grammar}" rows=4 oninput=${updateParams}/>
642 </div>
643 <div class="grammar-columns">
644 <div class="json-schema-controls">
645 <input type="text" name="prop-order" placeholder="Order: prop1,prop2,prop3" oninput=${updateGrammarJsonSchemaPropOrder} />
646 <button type="button" class="button-grammar" onclick=${convertJSONSchemaGrammar}>Convert JSON Schema</button>
647 </div>
648 </div>
649 </div>
650 `
651 );
652
653 const PromptControlFieldSet = () => (
654 html`
655 <fieldset>
656 <div class="input-container">
657 <label for="prompt" class="input-label">System</label>
658 <textarea
659 id="prompt"
660 class="persistent-input"
661 name="prompt"
662 placeholder="[Note] The following models do not support System Prompts by design:\nโข OpenChat\nโข Orion\nโข Phi-3\nโข Starling\nโข Yi-...-Chat"
663 value="${session.value.prompt}"
664 oninput=${updateSession}
665 ></textarea>
666 </div>
667 </fieldset>
668 `
669 );
670
671 const ChatConfigForm = () => (
672 html`
673 <fieldset class="dropdowns">
674 <div>
675 <select id="promptFormat" name="promptFormat" onchange=${updatePromptFormat}>
676 <option value="default">Prompt Style</option>
677 <option value=""></option>
678 <optgroup label="Common Prompt-Styles">
679 <option value="alpaca">Alpaca</option>
680 <option value="chatml">ChatML</option>
681 <option value="commandr">Command R/+</option>
682 <option value="llama2">Llama 2</option>
683 <option value="llama3">Llama 3</option>
684 <option value="phi3">Phi-3</option>
685 <option value="openchat">OpenChat/Starling</option>
686 <option value="vicuna">Vicuna</option>
687 <option value=""></option>
688 </optgroup>
689 <optgroup label="More Prompt-Styles">
690 <option value="vicuna">Airoboros L2</option>
691 <option value="vicuna">BakLLaVA-1</option>
692 <option value="alpaca">Code Cherry Pop</option>
693 <option value="deepseekCoder">Deepseek Coder</option>
694 <option value="chatml">Dolphin Mistral</option>
695 <option value="chatml">evolvedSeeker 1.3B</option>
696 <option value="vicuna">Goliath 120B</option>
697 <option value="vicuna">Jordan</option>
698 <option value="vicuna">LLaVA</option>
699 <option value="chatml">Leo Hessianai</option>
700 <option value="vicuna">Leo Mistral</option>
701 <option value="vicuna">Marx</option>
702 <option value="med42">Med42</option>
703 <option value="alpaca">MetaMath</option>
704 <option value="llama2">Mistral Instruct</option>
705 <option value="chatml">Mistral 7B OpenOrca</option>
706 <option value="alpaca">MythoMax</option>
707 <option value="neuralchat">Neural Chat</option>
708 <option value="vicuna">Nous Capybara</option>
709 <option value="nousHermes">Nous Hermes</option>
710 <option value="openchatMath">OpenChat Math</option>
711 <option value="chatml">OpenHermes 2.5-Mistral</option>
712 <option value="alpaca">Orca Mini v3</option>
713 <option value="orion">Orion</option>
714 <option value="vicuna">Samantha</option>
715 <option value="chatml">Samantha Mistral</option>
716 <option value="sauerkrautLM">SauerkrautLM</option>
717 <option value="vicuna">Scarlett</option>
718 <option value="starlingCode">Starling Coding</option>
719 <option value="alpaca">Sydney</option>
720 <option value="vicuna">Synthia</option>
721 <option value="vicuna">Tess</option>
722 <option value="yi34b">Yi-6/9/34B-Chat</option>
723 <option value="zephyr">Zephyr</option>
724 <option value=""></option>
725 </optgroup>
726 </select>
727 <select id="SystemPrompt" name="SystemPrompt" onchange=${updateSystemPrompt}>
728 <option value="default">System Prompt</option>
729 <option value="empty">None</option>
730 <option value="airoboros">Airoboros</option>
731 <option value="alpaca">Alpaca</option>
732 <option value="atlas">Atlas</option>
733 <option value="atlas_de">Atlas - DE</option>
734 <option value="cot">Chain of Tought</option>
735 <option value="commandrempty">Command R/+ (empty)</option>
736 <option value="commandrexample">Command R/+ (example)</option>
737 <option value="deduce">Critical Thinking</option>
738 <option value="deepseekcoder">Deepseek Coder</option>
739 <option value="jordan">Jordan</option>
740 <option value="leomistral">Leo Mistral</option>
741 <option value="med42">Med42</option>
742 <option value="migeltot">Migel's Tree of Thought</option>
743 <option value="mistralopenorca">Mistral OpenOrca</option>
744 <option value="orcamini">Orca Mini</option>
745 <option value="samantha">Samantha</option>
746 <option value="sauerkraut">Sauerkraut</option>
747 <option value="scarlett">Scarlett</option>
748 <option value="synthia">Synthia</option>
749 <option value="vicuna">Vicuna</option>
750 </select>
751 <!--<select id="systemLanguage" name="systemLanguage">-->
752 <!--<option value="default">English</option>-->
753 <!--<option value="DE">German</option>-->
754 <!--<option value="placeholderLanguage">Placeholder</option>-->
755 <!--</select>-->
756 </div>
757 </fieldset>
758 ${PromptControlFieldSet()}
759 <fieldset>
760 <details>
761 <summary><span class="summary-title" id="id_prompt-style">Prompt Style</span></summary>
762 <fieldset class="names">
763 <div>
764 <label for="user" id="id_user-name">User ID</label>
765 <input type="text" id="user" name="user" value="${session.value.user}" oninput=${updateSession} />
766 </div>
767 <div>
768 <label for="bot" id="id_bot-name">AI ID</label>
769 <input type="text" id="bot" name="char" value="${session.value.char}" oninput=${updateSession} />
770 </div>
771 </fieldset>
772 <div class="two-columns">
773 <div>
774 <div class="input-container">
775 <label for="template" class="input-label-sec" id_prompt-template>Prompt Template</label>
776 <textarea id="template" class="persistent-input-sec" name="template" value="${session.value.template}" rows=6 oninput=${updateSession}/>
777 </div>
778 </div>
779 <div>
780 <div class="input-container">
781 <label for="template" class="input-label-sec" id="id_history-template">Chat History</label>
782 <textarea id="history-template" class="persistent-input-sec" name="historyTemplate" value="${session.value.historyTemplate}" rows=1 oninput=${updateSession}/>
783 </div>
784 </div>
785 </div>
786 </details>
787 <details>
788 <summary><span class="summary-title" id="id_grammar-title" id_grammar-title>Grammar</span></summary>
789 ${GrammarControl()}
790 </details>
791
792 </fieldset>
793 `
794 );
795
796 const CompletionConfigForm = () => (
797 html`
798 ${PromptControlFieldSet()}
799 <fieldset>
800 <details>
801 <summary><span class="summary-title" id="id_grammar-title" id_grammar-title>Grammar</span></summary>
802 ${GrammarControl()}
803 </details>
804 </fieldset>
805 `
806 );
807// todo toggle button et api field et reset button in one nice row
808 return html`
809 <form>
810 <fieldset class="two">
811 <input type="checkbox" id="toggle" class="toggleCheckbox" onchange=${handleToggleChange} />
812 <label for="toggle" class="toggleContainer">
813 <div id="id_toggle-label-chat">Chat</div>
814 <div id="id_toggle-label-complete">Complete</div>
815 </label>
816 <fieldset>
817
818 <input type="text" id="api_key" class="apiKey" name="api_key" value="${params.value.api_key}" placeholder="Enter API key" oninput=${updateParams} />
819 </fieldset>
820
821 <${UserTemplateResetButton}/>
822 </fieldset>
823
824 ${session.value.type === 'chat' ? ChatConfigForm() : CompletionConfigForm()}
825
826 <fieldset class="params">
827 ${IntField({ label: "Prediction", title: "Set the maximum number of tokens to predict when generating text. Note: May exceed the set limit slightly if the last token is a partial multibyte character. When 0, no tokens will be generated but the prompt is evaluated into the cache. The value -1 means infinity. Default is 358", max: 2048, min: -1, step: 16, name: "n_predict", value: params.value.n_predict, })}
828 ${FloatField({ label: "Min-P sampling", title: "The minimum probability for a token to be considered, relative to the probability of the most likely token. Note that it's good practice to disable all other samplers aside from temperature when using min-p. It is also recommenend to go this approach. Default is 0.05 โ But consider higher values like ~ 0.4 for non-English text generation. The value 1.0 means disabled", max: 1.0, min: 0.0, name: "min_p", step: 0.01, value: params.value.min_p })}
829 ${FloatField({ label: "Repetition Penalty", title: "Control the repetition of token sequences in the generated text. Default is 1.1", max: 2.0, min: 0.0, name: "repeat_penalty", step: 0.01, value: params.value.repeat_penalty })}
830 ${FloatField({ label: "Temperature", title: "This will adjust the overall randomness of the generated text. It is the most common sampler. Default is 0.8 but consider using lower values for more factual texts or for non-English text generation", max: 2.0, min: 0.0, name: "temperature", step: 0.01, value: params.value.temperature })}
831 </fieldset>
832
833 <details>
834 <summary><span class="summary-title">Further Options</span></summary>
835 <fieldset class="params">
836 ${IntField({ label: "Top-K", title: "Limits the selection of the next token to the K most probable tokens. 1 means no randomness = greedy sampling. If set to 0, it means the entire vocabulary size is considered.", max: 100, min: 0, step: 1, name: "top_k", value: params.value.top_k })}
837 ${IntField({ label: "Penalize Last N", title: "The last n tokens that are taken into account to penalise repetitions. A value of 0 means that this function is deactivated and -1 means that the entire size of the context is taken into account.", max: 2048, min: 0, step: 16, name: "repeat_last_n", value: params.value.repeat_last_n })}
838 ${FloatField({ label: "Presence Penalty", title: "A penalty that is applied if certain tokens appear repeatedly in the generated text. A higher value leads to fewer repetitions.", max: 1.0, min: 0.0, name: "presence_penalty", step: 0.01, value: params.value.presence_penalty })}
839 ${FloatField({ label: "Frequency Penalty", title: "A penalty that is applied based on the frequency with which certain tokens occur in the training data set. A higher value results in rare tokens being favoured.", max: 1.0, min: 0.0, name: "frequency_penalty", step: 0.01, value: params.value.frequency_penalty })}
840 ${FloatField({ label: "Top-P", title: "Limits the selection of the next token to a subset of tokens whose combined probability reaches a threshold value P = top-P. If set to 1, it means the entire vocabulary size is considered.", max: 1.0, min: 0.0, name: "top_p", step: 0.01, value: params.value.top_p })}
841 ${FloatField({ label: "Typical-P", title: "Activates local typical sampling, a method used to limit the prediction of tokens that are atypical in the current context. The parameter p controls the strength of this limitation. A value of 1.0 means that this function is deactivated.", max: 1.0, min: 0.0, name: "typical_p", step: 0.01, value: params.value.typical_p })}
842 ${FloatField({ label: "XTC probability", title: "Sets the chance for token removal (checked once on sampler start)", max: 1.0, min: 0.0, name: "xtc_probability", step: 0.01, value: params.value.xtc_probability })}
843 ${FloatField({ label: "XTC threshold", title: "Sets a minimum probability threshold for tokens to be removed", max: 0.5, min: 0.0, name: "xtc_threshold", step: 0.01, value: params.value.xtc_threshold })}
844 ${FloatField({ label: "DRY Penalty Multiplier", title: "Set the DRY repetition penalty multiplier. Default is 0.0, which disables DRY.", max: 5.0, min: 0.0, name: "dry_multiplier", step: 0.01, value: params.value.dry_multiplier })}
845 ${FloatField({ label: "DRY Base", title: "Set the DRY repetition penalty base value. Default is 1.75", max: 3.0, min: 1.0, name: "dry_base", step: 0.01, value: params.value.dry_base })}
846 ${IntField({ label: "DRY Allowed Length", title: "Tokens that extend repetition beyond this receive exponentially increasing penalty. Default is 2", max: 10, min: 1, step: 1, name: "dry_allowed_length", value: params.value.dry_allowed_length })}
847 ${IntField({ label: "DRY Penalty Last N", title: "How many tokens to scan for repetitions. Default is -1, where 0 is disabled and -1 is context size", max: 2048, min: -1, step: 16, name: "dry_penalty_last_n", value: params.value.dry_penalty_last_n })}
848 ${IntField({ label: "Min Keep", title: "If greater than 0, samplers are forced to return N possible tokens at minimum. Default is 0", max: 10, min: 0, name: "min_keep", value: params.value.min_keep })}
849 </fieldset>
850
851 <hr style="height: 1px; background-color: #ececf1; border: none;" />
852
853 <fieldset class="three">
854 <label title="The Mirostat sampling method is an algorithm used in natural language processing to improve the quality and coherence of the generated texts. It is an at-runtime-adaptive method that aims to keep the entropy or surprise of a text within a desired range."><input type="radio" name="mirostat" value="0" checked=${params.value.mirostat == 0} oninput=${updateParamsInt} /> Mirostat off</label>
855 <label title="Mirostat version 1 was developed to adjust the probability of predictions so that the surprise in the text remains constant. This means that the algorithm tries to maintain a balance between predictable and surprising words so that the text is neither too monotonous nor too chaotic. V1 is recommended for longer writings, creative texts, etc."><input type="radio" name="mirostat" value="1" checked=${params.value.mirostat == 1} oninput=${updateParamsInt} /> Mirostat v1</label>
856 <label title="Mirostat version 2 builds on the idea of V1 but brings some improvements. V2 is recommended as a general purpose algorithm since it offers more precise control over entropy and reacts more quickly to unwanted deviations. As a result, the generated texts appear even more consistent and coherent, especially for everday life conversations."><input type="radio" name="mirostat" value="2" checked=${params.value.mirostat == 2} oninput=${updateParamsInt} /> Mirostat v2</label>
857 </fieldset>
858 <fieldset class="params">
859 ${FloatField({ label: "Entropy tau", title: "Tau controls the desired level of entropy (or 'surprise') in the text. A low tau (e.g. 0.5) would mean that a text is very predictable, but will also be very coherent. A high tau (e.g. 8.0) would mean that the text is very creative and surprising, but may also be difficult to follow because unlikely words will occur frequently.", max: 10.0, min: 0.0, name: "mirostat_tau", step: 0.01, value: params.value.mirostat_tau })}
860 ${FloatField({ label: "Learning-rate eta", title: "Eta determines how quickly the Mirostat algorithm adjusts its predictions to achieve the desired entropy. A learning rate that is too high can cause the algorithm to react too quickly and possibly become unstable, because the algorithm will try to maintain a balance between surprises and precision in the context of only a few words. In this way, 'the common thread' could be lost. Whereas a learning rate that is too low means that the algorithm reacts too slowly and a red thread becomes a heavy goods train that takes a long time to come to a halt and change a 'topic station'.", max: 1.0, min: 0.0, name: "mirostat_eta", step: 0.01, value: params.value.mirostat_eta })}
861 </fieldset>
862
863 <hr style="height: 1px; background-color: #ececf1; border: none;" />
864
865 <fieldset class="params">
866 ${IntField({ label: "Show Probabilities", title: "If greater than 0, the response also contains the probabilities of top N tokens for each generated token given the sampling settings. The tokens will be colored in gradient from green to red depending on their probabilities. Note that for temperature 0 the tokens are sampled greedily but token probabilities are still being calculated via a simple softmax of the logits without considering any other sampler settings. Defaults to 0", max: 10, min: 0, step: 1, name: "n_probs", value: params.value.n_probs })}
867 </fieldset>
868 </details>
869 </form>
870 `
871}
872
873 // todo - beautify apikey section with css
874
875 const probColor = (p) => {
876 const r = Math.floor(192 * (1 - p));
877 const g = Math.floor(192 * p);
878 return `rgba(${r},${g},0,0.3)`;
879 }
880
881 const Probabilities = (params) => {
882 return params.data.map(msg => {
883 const { completion_probabilities } = msg;
884 if (
885 !completion_probabilities ||
886 completion_probabilities.length === 0
887 ) return msg.content
888
889 if (completion_probabilities.length > 1) {
890 // Not for byte pair
891 if (completion_probabilities[0].content.startsWith('byte: \\')) return msg.content
892
893 const splitData = completion_probabilities.map(prob => ({
894 content: prob.content,
895 completion_probabilities: [prob]
896 }))
897 return html`<${Probabilities} data=${splitData} />`
898 }
899
900 const { probs, content } = completion_probabilities[0]
901 const found = probs.find(p => p.tok_str === msg.content)
902 const pColor = found ? probColor(found.prob) : 'transparent'
903
904 const popoverChildren = html`
905 <div class="prob-set">
906 ${probs.map((p, index) => {
907 return html`
908 <div
909 key=${index}
910 title=${`prob: ${p.prob}`}
911 style=${{
912 padding: '0.3em',
913 backgroundColor: p.tok_str === content ? probColor(p.prob) : 'transparent'
914 }}
915 >
916 <span>${p.tok_str}: </span>
917 <span>${Math.floor(p.prob * 100)}%</span>
918 </div>
919 `
920 })}
921 </div>
922 `
923
924 return html`
925 <${Popover} style=${{ backgroundColor: pColor }} popoverChildren=${popoverChildren}>
926 ${msg.content.match(/\n/gim) ? html`<br />` : msg.content}
927 </>
928 `
929 });
930 }
931
932 // poor mans markdown replacement
933 const Markdownish = (params) => {
934 const md = params.text
935 .replace(/&/g, '&')
936 .replace(/</g, '<')
937 .replace(/>/g, '>')
938 .replace(/(^|\n)#{1,6} ([^\n]*)(?=([^`]*`[^`]*`)*[^`]*$)/g, '$1<h3>$2</h3>')
939 .replace(/\*\*(.*?)\*\*(?=([^`]*`[^`]*`)*[^`]*$)/g, '<strong>$1</strong>')
940 .replace(/__(.*?)__(?=([^`]*`[^`]*`)*[^`]*$)/g, '<strong>$1</strong>')
941 .replace(/\*(.*?)\*(?=([^`]*`[^`]*`)*[^`]*$)/g, '<em>$1</em>')
942 .replace(/_(.*?)_(?=([^`]*`[^`]*`)*[^`]*$)/g, '<em>$1</em>')
943 .replace(/```.*?\n([\s\S]*?)```/g, '<pre><code>$1</code></pre>')
944 .replace(/`(.*?)`/g, '<code>$1</code>')
945 .replace(/\n/gim, '<br />');
946 return html`<span dangerouslySetInnerHTML=${{ __html: md }} />`;
947 };
948
949 const ModelGenerationInfo = (params) => {
950 if (!llamaStats.value) {
951 return html`<span/>`
952 }
953 return html`
954 <span class=generation-statistics>
955 ${llamaStats.value.tokens_predicted} predicted, ${llamaStats.value.tokens_cached} cached, ${llamaStats.value.timings.predicted_per_second.toFixed(2)} tokens per second
956 </span>
957 `
958 }
959
960 // simple popover impl
961 const Popover = (props) => {
962 const isOpen = useSignal(false);
963 const position = useSignal({ top: '0px', left: '0px' });
964 const buttonRef = useRef(null);
965 const popoverRef = useRef(null);
966
967 const togglePopover = () => {
968 if (buttonRef.current) {
969 const rect = buttonRef.current.getBoundingClientRect();
970 position.value = {
971 top: `${rect.bottom + window.scrollY}px`,
972 left: `${rect.left + window.scrollX}px`,
973 };
974 }
975 isOpen.value = !isOpen.value;
976 };
977
978 const handleClickOutside = (event) => {
979 if (popoverRef.current && !popoverRef.current.contains(event.target) && !buttonRef.current.contains(event.target)) {
980 isOpen.value = false;
981 }
982 };
983
984 useEffect(() => {
985 document.addEventListener('mousedown', handleClickOutside);
986 return () => {
987 document.removeEventListener('mousedown', handleClickOutside);
988 };
989 }, []);
990
991 return html`
992 <span style=${props.style} ref=${buttonRef} onClick=${togglePopover} contenteditable="true">${props.children}</span>
993 ${isOpen.value && html`
994 <${Portal} into="#portal">
995 <div
996 ref=${popoverRef}
997 class="popover-content"
998 style=${{
999 top: position.value.top,
1000 left: position.value.left,
1001 }}
1002 >
1003 ${props.popoverChildren}
1004 </div>
1005 </${Portal}>
1006 `}
1007 `;
1008 };
1009
1010 // Source: preact-portal (https://github.com/developit/preact-portal/blob/master/src/preact-portal.js)
1011 /** Redirect rendering of descendants into the given CSS selector */
1012 class Portal extends Component {
1013 componentDidUpdate(props) {
1014 for (let i in props) {
1015 if (props[i] !== this.props[i]) {
1016 return setTimeout(this.renderLayer);
1017 }
1018 }
1019 }
1020
1021 componentDidMount() {
1022 this.isMounted = true;
1023 this.renderLayer = this.renderLayer.bind(this);
1024 this.renderLayer();
1025 }
1026
1027 componentWillUnmount() {
1028 this.renderLayer(false);
1029 this.isMounted = false;
1030 if (this.remote && this.remote.parentNode) this.remote.parentNode.removeChild(this.remote);
1031 }
1032
1033 findNode(node) {
1034 return typeof node === 'string' ? document.querySelector(node) : node;
1035 }
1036
1037 renderLayer(show = true) {
1038 if (!this.isMounted) return;
1039
1040 // clean up old node if moving bases:
1041 if (this.props.into !== this.intoPointer) {
1042 this.intoPointer = this.props.into;
1043 if (this.into && this.remote) {
1044 this.remote = render(html`<${PortalProxy} />`, this.into, this.remote);
1045 }
1046 this.into = this.findNode(this.props.into);
1047 }
1048
1049 this.remote = render(html`
1050 <${PortalProxy} context=${this.context}>
1051 ${show && this.props.children || null}
1052 </${PortalProxy}>
1053 `, this.into, this.remote);
1054 }
1055
1056 render() {
1057 return null;
1058 }
1059 }
1060 // high-order component that renders its first child if it exists.
1061 // used as a conditional rendering proxy.
1062 class PortalProxy extends Component {
1063 getChildContext() {
1064 return this.props.context;
1065 }
1066 render({ children }) {
1067 return children || null;
1068 }
1069 }
1070
1071 function App(props) {
1072 return html`
1073 <div class="mode-${session.value.type}">
1074 <header>
1075 <h2>llama.cpp</h2>
1076 <div class="dropdown">
1077 <button class="dropbtn"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="10" stroke-width="2"/></svg></button>
1078 <div class="dropdown-content" id="theme-selector">
1079 <a href="/">Old UI</a>
1080 <a href="#" data-theme="default">Snow Storm</a>
1081 <a href="#" data-theme="polarnight">Polar Night</a>
1082 <a href="#" data-theme="ketivah">Ketivah</a>
1083 <a href="#" data-theme="mangotango">Mango Tango</a>
1084 <a href="#" data-theme="playground">Playground</a>
1085 <a href="#" data-theme="beeninorder">Been In Order</a>
1086 </div>
1087 </div>
1088 </header>
1089
1090 <main id="content">
1091 <${chatStarted.value ? ChatLog : ConfigForm} />
1092 </main>
1093
1094 <section id="write">
1095 <${session.value.type === 'chat' ? MessageInput : CompletionControls} />
1096 </section>
1097 <footer>
1098 <p><${ModelGenerationInfo} /></p>
1099 <p>Powered By <a href="https://github.com/ggml-org/llama.cpp#readme" target="_blank">llama.cpp</a> and <a href="https://ggml.ai/" target="_blank">ggml.ai</a></p>
1100 </footer>
1101 </div>
1102 `;
1103 }
1104
1105 document.addEventListener('DOMContentLoaded', function() {
1106 var themeSelector = document.getElementById('theme-selector');
1107 var themeLinks = themeSelector.querySelectorAll('a[data-theme]');
1108
1109 themeLinks.forEach(function(link) {
1110 link.addEventListener('click', function(event) {
1111 event.preventDefault(); // avoid default behaviour
1112 var selectedTheme = event.target.getAttribute('data-theme');
1113 changeTheme(selectedTheme);
1114 });
1115 });
1116
1117 function changeTheme(theme) {
1118 document.body.classList.remove('theme-default', 'theme-polarnight', 'theme-ketivah', 'theme-mangotango', 'theme-playground', 'theme-beeninorder');
1119 if (theme !== 'default') {
1120 document.body.classList.add('theme-' + theme);
1121 }
1122 localStorage.setItem('selected-theme', theme);
1123 }
1124
1125 // set the selected theme when loading the page
1126 var savedTheme = localStorage.getItem('selected-theme');
1127 if (savedTheme && savedTheme !== 'default') {
1128 document.body.classList.add('theme-' + savedTheme);
1129 // update the dropdown if it still exists
1130 var dropdown = document.getElementById('theme-selector-dropdown');
1131 if (dropdown) {
1132 dropdown.value = savedTheme;
1133 }
1134 }
1135});
1136
1137
1138// snapping of the slider to indicate 'disabled'
1139document.addEventListener('DOMContentLoaded', (event) => {
1140 // define an object that contains snap values and ranges for each slider
1141 const snapSettings = {
1142 temperature: { snapValue: 1.0, snapRangeMultiplier: 6 },
1143 min_p: { snapValue: 0.05, snapRangeMultiplier: 2 },
1144 xtc_probability: { snapValue: 0.0, snapRangeMultiplier: 4 },
1145 xtc_threshold: { snapValue: 0.5, snapRangeMultiplier: 4 },
1146 top_p: { snapValue: 1.0, snapRangeMultiplier: 4 },
1147 typical_p: { snapValue: 1.0, snapRangeMultiplier: 4 },
1148 repeat_penalty: { snapValue: 1.0, snapRangeMultiplier: 4 },
1149 presence_penalty: { snapValue: 0.0, snapRangeMultiplier: 4 },
1150 frequency_penalty: { snapValue: 0.0, snapRangeMultiplier: 4 },
1151 dry_multiplier: { snapValue: 0.0, snapRangeMultiplier: 4 },
1152 dry_base: { snapValue: 1.75, snapRangeMultiplier: 4 },
1153 };
1154 // add an event listener for each slider
1155 Object.keys(snapSettings).forEach(sliderName => {
1156 const slider = document.querySelector(`input[name="${sliderName}"]`);
1157 const settings = snapSettings[sliderName];
1158
1159 slider.addEventListener('input', (e) => {
1160 let value = parseFloat(e.target.value);
1161 const step = parseFloat(e.target.step);
1162 const snapRange = step * settings.snapRangeMultiplier;
1163 const valueDisplay = document.getElementById(`${e.target.name}-value`);
1164
1165 if (value >= settings.snapValue - snapRange && value <= settings.snapValue + snapRange) {
1166 value = settings.snapValue; // set value to the snap value
1167 e.target.value = value; // update the slider value
1168 }
1169 // update the displayed value
1170 if (valueDisplay) {
1171 valueDisplay.textContent = value.toFixed(2); // display value with two decimal places
1172 }
1173 });
1174 });
1175});
1176
1177 render(h(App), document.querySelector('#container'));
1178
1179 </script>
1180</head>
1181
1182<body>
1183
1184 <div id="container">
1185 <input type="file" id="fileInput" accept="image/*" style="display: none;">
1186 </div>
1187 <div id="portal"></div>
1188</body>
1189
1190</html>