1 line
24 KiB
JSON
1 line
24 KiB
JSON
{"repo": "ahoward/drawohara.io", "files": {"lib/ai.rb": {"9730e5788cb5989391c6bd89a408e718f0d1ca42": {"t": 1785745744.606673, "n": 11335, "h": "630529e79df2f7bf", "c": "require 'bundler/setup'\n\nrequire 'thread'\nrequire 'json'\nrequire 'time'\nrequire 'securerandom'\nrequire 'fileutils'\n\nrequire 'map'\nrequire 'anthropic'\nrequire 'groq'\nrequire 'mistral-ai'\nrequire 'mistral-ai/errors'\n\n\nrequire_relative 'rate_limiter.rb'\nrequire_relative 'env.rb'\n\nmodule AI\n def AI.provider\n AI::Groq\n #AI::Mistral\n #AI::Anthropic\n #AI::DeepSeek\n end\n\n def AI.completion_for(prompt, temperature:0.7, format:'txt')\n provider.completion_for(prompt, temperature:, format:)\n end\n\n def AI.json_parse_liberally(json)\n begin\n JSON.parse(json)\n rescue => error\n begin\n json.gsub!('```json', '')\n json.gsub!('```', '')\n JSON.parse(json)\n rescue\n raise error\n end\n end\n end\n\n def AI.count_tokens(*args)\n string = args.join(\"\\n\")\n words = string.scan(/\\w+/)\n words_per_token = 3.0/4.0\n (words.size * 1/words_per_token).to_i\n end\n\n class Groq\n @@API_KEY = ENV.fetch('GROQ_API_KEY')\n @@MODEL = 'llama-3.3-70b-versatile'\n #@@MODEL = 'compound-beta'\n @@MAX_TOKENS = 128_000\n @@TIMEOUT = 420\n\n @@RPM = 30 #60\n @@RATE_LIMTER = RateLimiter.new(name: 'groq', rpm: @@RPM - 1)\n\n attr_reader :client\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n @client = ::Groq::Client.new(api_key: @api_key, model_id: @@MODEL, timeout: @timeout)\n end\n\n def completion_for(*args, role:'user', system:nil, prompt:nil, temperature:nil, format:nil)\n content = [prompt || args].join(\"\\n\")\n Groq.try_hard do\n Groq.rate_limit do\n client.chat(content).fetch('content')\n end\n end\n end\n\n def Groq.completion_for(...)\n new.completion_for(...)\n end\n\n def Groq.rate_limit(&block)\n @@RATE_LIMTER.limit(&block)\n end\n\n def Groq.try_hard(*args, &block)\n if @try_hard == false\n return block.call\n end\n\n n = 6\n errors = []\n fatal = [\n RangeError,\n NameError,\n ArgumentError,\n Faraday::BadRequestError,\n Faraday::ClientError\n ]\n\n n.times do |i|\n begin\n return block.call\n rescue => error\n raise error if fatal.include?(error.class)\n errors.push(error)\n s = (2 ** (i + 2))\n warn \"Groq.try_hard: sleep(#{ s }), #{ error.class }[#{ error.message }]\"\n sleep(s)\n end\n end\n\n raise errors.last\n end\n\n def Groq.try_hard=(try_hard)\n @try_hard = !!try_hard\n end\n end\n\n class Anthropic\n @@API_KEY = ENV.fetch('ANTHROPIC_API_KEY')\n @@MODEL = 'claude-3-5-sonnet-latest'\n @@MAX_TOKENS = 42420\n @@TIMEOUT = 420\n\n @@RPM = 50\n @@RATE_LIMTER = RateLimiter.new(name: 'anthropic', rpm: @@RPM - 1)\n\n attr_reader :client\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n @client = ::Anthropic::Client.new(access_token: @api_key, request_timeout: @timeout)\n end\n\n def chat_completions(parameters = {}, **kws)\n parameters = Map.for(parameters).update(kws)\n\n parameters.keys.each do |key|\n parameters.delete(key) if parameters[key].nil?\n end\n\n parameters[:model] = @@MODEL unless parameters.has_key?(:model)\n\n parameters[:max_tokens] = @@MAX_TOKENS unless parameters.has_key?(:max_tokens)\n\n Anthropic.try_hard do\n Anthropic.rate_limit do\n Map.for(client.messages(parameters:))\n end\n end\n end\n\n def Anthropic.completion_for(...)\n new.completion_for(...)\n end\n\n def completion_for(*args, role:'user', system:nil, prompt:nil, temperature:nil, format:nil)\n content = [prompt || args].join(\"\\n\")\n messages = []\n messages << {role:, content:}\n result = chat_completions(system:, messages:)\n result.get(:content, 0, :text)\n end\n\n def Anthropic.rate_limit(&block)\n @@RATE_LIMTER.limit(&block)\n end\n\n def Anthropic.try_hard(*args, &block)\n if @try_hard == false\n return block.call\n end\n\n n = 7\n errors = []\n fatal = [\n Faraday::BadRequestError,\n Faraday::ClientError\n ]\n\n n.times do |i|\n begin\n return block.call\n rescue => error\n raise error if fatal.include?(error.class)\n errors.push(error)\n s = (2 ** i)\n warn \"Anthropic.try_hard: sleep(#{ s }), #{ error.class }[#{ error.message }]\"\n sleep(s)\n end\n end\n\n raise errors.last\n end\n\n def Anthropic.try_hard=(try_hard)\n @try_hard = !!try_hard\n end\n end\n\n class DeepSeek\n @@BASE_URL = 'https://api.deepseek.com'\n @@API_KEY = ENV.fetch('DEEPSEEK_API_KEY')\n @@MODEL = 'deepseek-reasoner'\n @@TIMEOUT = 420\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n end\n\n def chat_completions(params = {}, **kws)\n params = Map.for(params).update(kws)\n params[:model] = @@MODEL unless params.has_key?(:model)\n params[:stream] = false unless params.has_key?(:stream)\n\n=begin\n data = params.to_hash.to_json\n cmd = \"curl https://api.deepseek.com/chat/completions -s -H 'Content-Type: application/json' -H 'Authorization: Bearer #{ @api_key }' -d '#{ data }'\"\n puts cmd\n oe = `#{ cmd }`\n return Map.for(JSON.parse(oe))\n=end\n\n uri = URI.parse('https://api.deepseek.com/chat/completions')\n http = Net::HTTP.new(uri.host, uri.port)\n http.use_ssl = true\n\n request = Net::HTTP::Post.new(uri.path)\n request['Content-Type'] = 'application/json'\n request['Authorization'] = 'Bearer %s' % @api_key\n\n request.body = params.to_json\n\n response = http.request(request)\n\n if response.is_a?(Net::HTTPSuccess)\n Map.for(JSON.parse(response.body))\n else\n raise \"Error: #{ response.code } - #{ response.message }\\n\\n#{ response.body }\"\n end\n end\n\n def DeepSeek.completion_for(...)\n result = new.completion_for(...)\n end\n\n def completion_for(*args, system:nil, prompt:nil, temperature:nil, format:nil)\n user = [prompt || args].join(\"\\n\")\n\n messages = []\n\n if system\n messages << {role: 'system', content: [system].join(\"\\n\")}\n end\n\n messages << {role: 'user', content: user}\n\n result = chat_completions(messages:)\n\n result.get(:choices, 0, :message, :content)\n end\n\n=begin\n{\"id\"=>\"6a619c81-0ea7-4b98-8a82-2fdd886e601a\",\n \"object\"=>\"chat.completion\",\n \"created\"=>1738471159,\n \"model\"=>\"deepseek-reasoner\",\n \"choices\"=>\n [{\"index\"=>0,\n \"message\"=>\n {\"role\"=>\"assistant\",\n \"content\"=>\"Sure! Here's a light-hearted one: \\n\\nWhy don’t scientists trust atoms? \\n…Because they *make up everything*! \\n\\n(Atomic puns are the *element* of a good joke, right?) 😄\",\n \"reasoning_content\"=>\n \"Okay, the user asked for a joke. I need to come up with something light-hearted and appropriate. Let's see, maybe something tech-related since I'm an AI. How about a classic setup with a pun.\\n\\nWhy don't scientists trust atoms? Because they make up everything! That's a good one. It's simple, has a pun, and relates to science which ties into the AI theme. Let me check if there's any chance it might be offensive or not. No, atoms are a safe topic. Alright, that should work.\"},\n \"logprobs\"=>nil,\n \"finish_reason\"=>\"stop\"}],\n \"usage\"=>\n {\"prompt_tokens\"=>9,\n \"completion_tokens\"=>161,\n \"total_tokens\"=>170,\n \"prompt_tokens_details\"=>{\"cached_tokens\"=>0},\n \"completion_tokens_details\"=>{\"reasoning_tokens\"=>112},\n \"prompt_cache_hit_tokens\"=>0,\n \"prompt_cache_miss_tokens\"=>9},\n \"system_fingerprint\"=>\"fp_7e73fd9a08\"}\n=end\n end\n\n class Mistral\n @@API_KEY = ENV.fetch('MISTRAL_API_KEY')\n @@MODEL = 'pixtral-large-latest'\n @@TIMEOUT = 420\n\n @@RPS = 20\n @@RATE_LIMTER = RateLimiter.new(name: 'mistral', rps: @@RPS - 1)\n\n attr_reader :client\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n @client = ::Mistral.new(\n credentials: { api_key: @api_key },\n options: {\n connection: { request: { timeout: @timeout } },\n }\n )\n end\n\n %w[\n embeddings\n chat_completions\n agent_chat_completions\n ].each do |method|\n class_eval <<-____, __FILE__, __LINE__ + 1\n def #{ method }(*args, **kws, &block)\n Mistral.try_hard do\n result =\n Mistral.rate_limit do\n client.#{ method }(*args, **kws, &block)\n end\n\n return Map.for(result)\n end\n end\n ____\n end\n\n def Mistral.completion_for(prompt, temperature:0.7, model:@@MODEL, format: 'txt')\n mistral = new\n\n messages =\n [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": prompt.to_s,\n },\n ]\n },\n ]\n\n params = {\n temperature: temperature,\n model: model,\n messages: messages,\n }\n\n if format.to_s == 'json'\n params[:response_format] = {type: \"json_object\"}\n end\n\n result =\n case\n when model =~ /^ag:/\n mistral.agent_completions(params)\n else\n mistral.chat_completions(params)\n end\n\n return result.get(:choices, 0, :message, :content)\n end\n\n def embeddings_for(input, *inputs, model: 'mistral-embed')\n inputs =\n [input.to_s, *inputs.map(&:to_s)]\n\n result =\n embeddings(\n { model: model,\n input: inputs,\n }\n )\n\n inputs.size.times.map do |i|\n result.fetch(:data).fetch(i).fetch(:embedding)\n end\n end\n\n def embedding_for(input, model: 'mistral-embed')\n embeddings_for(input, model:).first\n end\n\n def Mistral.embeddings_for(...)\n new.embeddings_for(...)\n end\n\n def Mistral.embedding_for(...)\n new.embedding_for(...)\n end\n\n def Mistral.rate_limit(&block)\n @@RATE_LIMTER.limit(&block)\n end\n\n def Mistral.try_hard(*args, &block)\n if @try_hard == false\n return block.call\n end\n\n n = 7\n errors = []\n\n n.times do |i|\n begin\n return block.call\n rescue ::Mistral::Errors::RequestError, Faraday::TooManyRequestsError => error\n errors.push(error)\n s = (2 ** i)\n warn \"Mistral.try_hard: sleep(#{ s }), #{ error.class }[#{ error.message }]\"\n sleep(s)\n end\n end\n\n raise errors.last\n end\n\n def Mistral.try_hard=(try_hard)\n @try_hard = !!try_hard\n end\n end\nend\n\n# monkey-patch\nmodule Mistral\n module Controllers\n class Client\n def agent_chat_completions(payload, server_sent_events: nil, &callback)\n server_sent_events = false if payload[:stream] != true\n request('v1/agents/completions', payload, server_sent_events:, &callback)\n end\n end\n end\nend\n\n class LLama\n #completion = AI::Mistral.try_hard{ AI::Mistral.completion_for(prompt) }\n #cmd = \"ollama run llama3.2 /dev/stdin\"\n #stdin = prompt\n #stdout = IO.popen(cmd, 'w+'){|io| io.write(stdin); io.close_write; io.read}\n #stdout.strip\n end\n"}, "bfd44c562165a80cd2197d4cd62ef88e47ffefd8": {"t": 1785756104.1107695, "n": 11335, "h": "630529e79df2f7bf", "c": "require 'bundler/setup'\n\nrequire 'thread'\nrequire 'json'\nrequire 'time'\nrequire 'securerandom'\nrequire 'fileutils'\n\nrequire 'map'\nrequire 'anthropic'\nrequire 'groq'\nrequire 'mistral-ai'\nrequire 'mistral-ai/errors'\n\n\nrequire_relative 'rate_limiter.rb'\nrequire_relative 'env.rb'\n\nmodule AI\n def AI.provider\n AI::Groq\n #AI::Mistral\n #AI::Anthropic\n #AI::DeepSeek\n end\n\n def AI.completion_for(prompt, temperature:0.7, format:'txt')\n provider.completion_for(prompt, temperature:, format:)\n end\n\n def AI.json_parse_liberally(json)\n begin\n JSON.parse(json)\n rescue => error\n begin\n json.gsub!('```json', '')\n json.gsub!('```', '')\n JSON.parse(json)\n rescue\n raise error\n end\n end\n end\n\n def AI.count_tokens(*args)\n string = args.join(\"\\n\")\n words = string.scan(/\\w+/)\n words_per_token = 3.0/4.0\n (words.size * 1/words_per_token).to_i\n end\n\n class Groq\n @@API_KEY = ENV.fetch('GROQ_API_KEY')\n @@MODEL = 'llama-3.3-70b-versatile'\n #@@MODEL = 'compound-beta'\n @@MAX_TOKENS = 128_000\n @@TIMEOUT = 420\n\n @@RPM = 30 #60\n @@RATE_LIMTER = RateLimiter.new(name: 'groq', rpm: @@RPM - 1)\n\n attr_reader :client\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n @client = ::Groq::Client.new(api_key: @api_key, model_id: @@MODEL, timeout: @timeout)\n end\n\n def completion_for(*args, role:'user', system:nil, prompt:nil, temperature:nil, format:nil)\n content = [prompt || args].join(\"\\n\")\n Groq.try_hard do\n Groq.rate_limit do\n client.chat(content).fetch('content')\n end\n end\n end\n\n def Groq.completion_for(...)\n new.completion_for(...)\n end\n\n def Groq.rate_limit(&block)\n @@RATE_LIMTER.limit(&block)\n end\n\n def Groq.try_hard(*args, &block)\n if @try_hard == false\n return block.call\n end\n\n n = 6\n errors = []\n fatal = [\n RangeError,\n NameError,\n ArgumentError,\n Faraday::BadRequestError,\n Faraday::ClientError\n ]\n\n n.times do |i|\n begin\n return block.call\n rescue => error\n raise error if fatal.include?(error.class)\n errors.push(error)\n s = (2 ** (i + 2))\n warn \"Groq.try_hard: sleep(#{ s }), #{ error.class }[#{ error.message }]\"\n sleep(s)\n end\n end\n\n raise errors.last\n end\n\n def Groq.try_hard=(try_hard)\n @try_hard = !!try_hard\n end\n end\n\n class Anthropic\n @@API_KEY = ENV.fetch('ANTHROPIC_API_KEY')\n @@MODEL = 'claude-3-5-sonnet-latest'\n @@MAX_TOKENS = 42420\n @@TIMEOUT = 420\n\n @@RPM = 50\n @@RATE_LIMTER = RateLimiter.new(name: 'anthropic', rpm: @@RPM - 1)\n\n attr_reader :client\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n @client = ::Anthropic::Client.new(access_token: @api_key, request_timeout: @timeout)\n end\n\n def chat_completions(parameters = {}, **kws)\n parameters = Map.for(parameters).update(kws)\n\n parameters.keys.each do |key|\n parameters.delete(key) if parameters[key].nil?\n end\n\n parameters[:model] = @@MODEL unless parameters.has_key?(:model)\n\n parameters[:max_tokens] = @@MAX_TOKENS unless parameters.has_key?(:max_tokens)\n\n Anthropic.try_hard do\n Anthropic.rate_limit do\n Map.for(client.messages(parameters:))\n end\n end\n end\n\n def Anthropic.completion_for(...)\n new.completion_for(...)\n end\n\n def completion_for(*args, role:'user', system:nil, prompt:nil, temperature:nil, format:nil)\n content = [prompt || args].join(\"\\n\")\n messages = []\n messages << {role:, content:}\n result = chat_completions(system:, messages:)\n result.get(:content, 0, :text)\n end\n\n def Anthropic.rate_limit(&block)\n @@RATE_LIMTER.limit(&block)\n end\n\n def Anthropic.try_hard(*args, &block)\n if @try_hard == false\n return block.call\n end\n\n n = 7\n errors = []\n fatal = [\n Faraday::BadRequestError,\n Faraday::ClientError\n ]\n\n n.times do |i|\n begin\n return block.call\n rescue => error\n raise error if fatal.include?(error.class)\n errors.push(error)\n s = (2 ** i)\n warn \"Anthropic.try_hard: sleep(#{ s }), #{ error.class }[#{ error.message }]\"\n sleep(s)\n end\n end\n\n raise errors.last\n end\n\n def Anthropic.try_hard=(try_hard)\n @try_hard = !!try_hard\n end\n end\n\n class DeepSeek\n @@BASE_URL = 'https://api.deepseek.com'\n @@API_KEY = ENV.fetch('DEEPSEEK_API_KEY')\n @@MODEL = 'deepseek-reasoner'\n @@TIMEOUT = 420\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n end\n\n def chat_completions(params = {}, **kws)\n params = Map.for(params).update(kws)\n params[:model] = @@MODEL unless params.has_key?(:model)\n params[:stream] = false unless params.has_key?(:stream)\n\n=begin\n data = params.to_hash.to_json\n cmd = \"curl https://api.deepseek.com/chat/completions -s -H 'Content-Type: application/json' -H 'Authorization: Bearer #{ @api_key }' -d '#{ data }'\"\n puts cmd\n oe = `#{ cmd }`\n return Map.for(JSON.parse(oe))\n=end\n\n uri = URI.parse('https://api.deepseek.com/chat/completions')\n http = Net::HTTP.new(uri.host, uri.port)\n http.use_ssl = true\n\n request = Net::HTTP::Post.new(uri.path)\n request['Content-Type'] = 'application/json'\n request['Authorization'] = 'Bearer %s' % @api_key\n\n request.body = params.to_json\n\n response = http.request(request)\n\n if response.is_a?(Net::HTTPSuccess)\n Map.for(JSON.parse(response.body))\n else\n raise \"Error: #{ response.code } - #{ response.message }\\n\\n#{ response.body }\"\n end\n end\n\n def DeepSeek.completion_for(...)\n result = new.completion_for(...)\n end\n\n def completion_for(*args, system:nil, prompt:nil, temperature:nil, format:nil)\n user = [prompt || args].join(\"\\n\")\n\n messages = []\n\n if system\n messages << {role: 'system', content: [system].join(\"\\n\")}\n end\n\n messages << {role: 'user', content: user}\n\n result = chat_completions(messages:)\n\n result.get(:choices, 0, :message, :content)\n end\n\n=begin\n{\"id\"=>\"6a619c81-0ea7-4b98-8a82-2fdd886e601a\",\n \"object\"=>\"chat.completion\",\n \"created\"=>1738471159,\n \"model\"=>\"deepseek-reasoner\",\n \"choices\"=>\n [{\"index\"=>0,\n \"message\"=>\n {\"role\"=>\"assistant\",\n \"content\"=>\"Sure! Here's a light-hearted one: \\n\\nWhy don’t scientists trust atoms? \\n…Because they *make up everything*! \\n\\n(Atomic puns are the *element* of a good joke, right?) 😄\",\n \"reasoning_content\"=>\n \"Okay, the user asked for a joke. I need to come up with something light-hearted and appropriate. Let's see, maybe something tech-related since I'm an AI. How about a classic setup with a pun.\\n\\nWhy don't scientists trust atoms? Because they make up everything! That's a good one. It's simple, has a pun, and relates to science which ties into the AI theme. Let me check if there's any chance it might be offensive or not. No, atoms are a safe topic. Alright, that should work.\"},\n \"logprobs\"=>nil,\n \"finish_reason\"=>\"stop\"}],\n \"usage\"=>\n {\"prompt_tokens\"=>9,\n \"completion_tokens\"=>161,\n \"total_tokens\"=>170,\n \"prompt_tokens_details\"=>{\"cached_tokens\"=>0},\n \"completion_tokens_details\"=>{\"reasoning_tokens\"=>112},\n \"prompt_cache_hit_tokens\"=>0,\n \"prompt_cache_miss_tokens\"=>9},\n \"system_fingerprint\"=>\"fp_7e73fd9a08\"}\n=end\n end\n\n class Mistral\n @@API_KEY = ENV.fetch('MISTRAL_API_KEY')\n @@MODEL = 'pixtral-large-latest'\n @@TIMEOUT = 420\n\n @@RPS = 20\n @@RATE_LIMTER = RateLimiter.new(name: 'mistral', rps: @@RPS - 1)\n\n attr_reader :client\n\n def initialize(api_key: @@API_KEY, timeout: @@TIMEOUT)\n @api_key = api_key\n @timeout = timeout\n @client = ::Mistral.new(\n credentials: { api_key: @api_key },\n options: {\n connection: { request: { timeout: @timeout } },\n }\n )\n end\n\n %w[\n embeddings\n chat_completions\n agent_chat_completions\n ].each do |method|\n class_eval <<-____, __FILE__, __LINE__ + 1\n def #{ method }(*args, **kws, &block)\n Mistral.try_hard do\n result =\n Mistral.rate_limit do\n client.#{ method }(*args, **kws, &block)\n end\n\n return Map.for(result)\n end\n end\n ____\n end\n\n def Mistral.completion_for(prompt, temperature:0.7, model:@@MODEL, format: 'txt')\n mistral = new\n\n messages =\n [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": prompt.to_s,\n },\n ]\n },\n ]\n\n params = {\n temperature: temperature,\n model: model,\n messages: messages,\n }\n\n if format.to_s == 'json'\n params[:response_format] = {type: \"json_object\"}\n end\n\n result =\n case\n when model =~ /^ag:/\n mistral.agent_completions(params)\n else\n mistral.chat_completions(params)\n end\n\n return result.get(:choices, 0, :message, :content)\n end\n\n def embeddings_for(input, *inputs, model: 'mistral-embed')\n inputs =\n [input.to_s, *inputs.map(&:to_s)]\n\n result =\n embeddings(\n { model: model,\n input: inputs,\n }\n )\n\n inputs.size.times.map do |i|\n result.fetch(:data).fetch(i).fetch(:embedding)\n end\n end\n\n def embedding_for(input, model: 'mistral-embed')\n embeddings_for(input, model:).first\n end\n\n def Mistral.embeddings_for(...)\n new.embeddings_for(...)\n end\n\n def Mistral.embedding_for(...)\n new.embedding_for(...)\n end\n\n def Mistral.rate_limit(&block)\n @@RATE_LIMTER.limit(&block)\n end\n\n def Mistral.try_hard(*args, &block)\n if @try_hard == false\n return block.call\n end\n\n n = 7\n errors = []\n\n n.times do |i|\n begin\n return block.call\n rescue ::Mistral::Errors::RequestError, Faraday::TooManyRequestsError => error\n errors.push(error)\n s = (2 ** i)\n warn \"Mistral.try_hard: sleep(#{ s }), #{ error.class }[#{ error.message }]\"\n sleep(s)\n end\n end\n\n raise errors.last\n end\n\n def Mistral.try_hard=(try_hard)\n @try_hard = !!try_hard\n end\n end\nend\n\n# monkey-patch\nmodule Mistral\n module Controllers\n class Client\n def agent_chat_completions(payload, server_sent_events: nil, &callback)\n server_sent_events = false if payload[:stream] != true\n request('v1/agents/completions', payload, server_sent_events:, &callback)\n end\n end\n end\nend\n\n class LLama\n #completion = AI::Mistral.try_hard{ AI::Mistral.completion_for(prompt) }\n #cmd = \"ollama run llama3.2 /dev/stdin\"\n #stdin = prompt\n #stdout = IO.popen(cmd, 'w+'){|io| io.write(stdin); io.close_write; io.read}\n #stdout.strip\n end\n"}}}} |