Commit 1025909
Changed files (3)
ext
elelem
llama
lib
elelem
llama
ext/elelem/llama/extconf.rb
@@ -14,8 +14,8 @@ DARWIN = RbConfig::CONFIG["host_os"] =~ /darwin/
class BuildError < StandardError; end
def run(*cmd)
- warn "elelem: + #{cmd.join(' ')}"
- system(*cmd) || raise(BuildError, "build step failed: #{cmd.join(' ')}")
+ warn "elelem: + #{cmd.join(" ")}"
+ system(*cmd) || raise(BuildError, "build step failed: #{cmd.join(" ")}")
end
def which(cmd)
@@ -27,6 +27,7 @@ end
def vulkan_loader?
return true if which("vulkaninfo")
+
%w[/usr/lib64 /usr/lib /usr/local/lib /lib64 /lib].any? do |dir|
!Dir.glob(File.join(dir, "libvulkan.so*")).empty?
end
@@ -48,18 +49,20 @@ end
def gpu_flags(backend)
{
- "cpu" => [], # GGML_NATIVE is ON by default -> host CPU SIMD
+ "cpu" => [], # GGML_NATIVE is ON by default -> host CPU SIMD
"vulkan" => ["-DGGML_VULKAN=ON"],
- "cuda" => ["-DGGML_CUDA=ON"],
- "hip" => ["-DGGML_HIP=ON", "-DCMAKE_HIP_ARCHITECTURES=#{ENV.fetch("ELELEM_HIP_ARCH") { hip_gfx_target || "gfx1100" }}"],
- "metal" => ["-DGGML_METAL=ON", "-DGGML_METAL_EMBED_LIBRARY=ON"]
+ "cuda" => ["-DGGML_CUDA=ON"],
+ "hip" => ["-DGGML_HIP=ON", "-DCMAKE_HIP_ARCHITECTURES=#{ENV.fetch("ELELEM_HIP_ARCH") do
+ hip_gfx_target || "gfx1100"
+ end}"],
+ "metal" => ["-DGGML_METAL=ON", "-DGGML_METAL_EMBED_LIBRARY=ON"]
}.fetch(backend) { abort "elelem: unknown backend #{backend.inspect}" }
end
def detect_backend
forced = ENV["ELELEM_LLAMA_BACKEND"].to_s.strip.downcase
unless forced.empty? || forced == "auto" || VALID_BACKENDS.include?(forced)
- abort "elelem: ELELEM_LLAMA_BACKEND=#{forced.inspect} invalid; use auto|#{VALID_BACKENDS.join('|')}"
+ abort "elelem: ELELEM_LLAMA_BACKEND=#{forced.inspect} invalid; use auto|#{VALID_BACKENDS.join("|")}"
end
return forced unless forced.empty? || forced == "auto"
@@ -67,6 +70,7 @@ def detect_backend
return "cuda" if which("nvcc")
return "vulkan" if which("glslc") && vulkan_loader?
return "hip" if hip_available?
+
"cpu"
end
@@ -111,11 +115,11 @@ def link_shim(libdir)
cxx = ENV["CXX"] || "c++"
link_flags = if DARWIN
- ["-Wl,-rpath,@loader_path", "-Wl,-install_name,@rpath/libelelem_llama.dylib",
- "-framework", "Metal", "-framework", "Foundation", "-framework", "Accelerate"]
- else
- ["-Wl,-rpath,$ORIGIN"]
- end
+ ["-Wl,-rpath,@loader_path", "-Wl,-install_name,@rpath/libelelem_llama.dylib",
+ "-framework", "Metal", "-framework", "Foundation", "-framework", "Accelerate"]
+ else
+ ["-Wl,-rpath,$ORIGIN"]
+ end
run(cxx, "-std=c++17", "-O2", "-Wall", "-Wextra", "-shared", "-fPIC",
"-I", File.join(VENDOR, "include"),
"-I", File.join(VENDOR, "ggml", "include"),
@@ -133,6 +137,7 @@ begin
link_shim(File.join(BUILD_DIR, "bin"))
rescue BuildError => e
raise if backend == "cpu"
+
warn "elelem: #{backend} build failed (#{e.message}); falling back to CPU"
FileUtils.rm_rf(BUILD_DIR)
backend = "cpu"
lib/elelem/llama/provider.rb
@@ -61,10 +61,10 @@ module Elelem
Elelem.logger.warn("llama: generate error: #{result["error"]}") if result["error"]
if result["ms_decode"]
Elelem.logger.debug(format(
- "llama: reset=%.0fms prefill=%.0fms (n=%d, %d reused) decode=%.0fms (n=%d)",
- result["ms_reset"], result["ms_prefill"], result["n_prompt"], result["n_reused"].to_i,
- result["ms_decode"], result["n_decoded"]
- ))
+ "llama: reset=%.0fms prefill=%.0fms (n=%d, %d reused) decode=%.0fms (n=%d)",
+ result["ms_reset"], result["ms_prefill"], result["n_prompt"], result["n_reused"].to_i,
+ result["ms_decode"], result["n_decoded"]
+ ))
end
if result["tool_calls"].to_a.empty? && !tools.empty? && result["content"].to_s.include?("\"name\"")
Elelem.logger.debug("llama: no tool calls parsed, tools offered")
@@ -78,7 +78,8 @@ module Elelem
content = "[error: #{result["error"]}]"
elsif result["truncated"] && content.empty? && result.fetch("tool_calls", []).empty?
limit = @max_tokens.positive? ? "max_tokens" : "available context"
- Elelem.logger.warn("llama: hit #{limit} (#{result["n_decoded"]}/#{result["budget"]}) before producing a reply")
+ Elelem.logger.warn("llama: hit #{limit} (#{result["n_decoded"]}/#{result["budget"]}) before producing " \
+ "a reply")
content = "[no reply: ran out of output tokens before finishing]"
end
block&.call(type: "saying", text: content) unless content.empty?
lib/elelem/llama.rb
@@ -11,16 +11,17 @@ Elelem.configure do |config|
config.provider(:llama) do
gpu = %w[vulkan cuda metal].include?(Elelem::Llama::Provider.backend)
- default_model = -> {
+ default_model = lambda {
dir = File.expand_path("~/.agents/models")
link = File.join(dir, "default.gguf")
return link if File.symlink?(link) || File.exist?(link)
- models = Dir[File.join(dir, "*.gguf")].sort
+ models = Dir[File.join(dir, "*.gguf")]
case models.length
when 1 then models.first
when 0 then raise "no .gguf model found in #{dir}. Set ELELEM_GGUF_MODEL=/path/to/model.gguf"
- else raise "multiple .gguf models found in #{dir}. Set ELELEM_GGUF_MODEL=/path/to/model.gguf or symlink #{link} to the one to use by default"
+ else raise "multiple .gguf models found in #{dir}. Set ELELEM_GGUF_MODEL=/path/to/model.gguf or symlink " \
+ "#{link} to the one to use by default"
end
}