diff --git a/README.md b/README.md index b69b4b9..89e1cd0 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ The following LLM providers are currently supported besides OpenAI: - [Perplexity.ai](https://www.perplexity.ai/pro) Pro users have $5/month free API credits available (the default PPLX agent uses Mixtral-8x7b). - [Anthropic](https://www.anthropic.com/api) to access Claude models, which currently outperform GPT-4 in some benchmarks. - [Google Gemini](https://ai.google.dev/) with a quite generous free range but some geo-restrictions (EU). +- [x.ai](https://x.ai/api) to access Grok-4 with pre-paid credit plans (No free credit available at this moment). - Any other "OpenAI chat/completions" compatible endpoint (Azure, LM Studio, etc.) Below is an example of the relevant configuration part enabling some of these. The `secret` field has the same capabilities as `openai_api_key` (which is still supported for compatibility). @@ -171,6 +172,11 @@ Below is an example of the relevant configuration part enabling some of these. T endpoint = "https://api.anthropic.com/v1/messages", secret = os.getenv("ANTHROPIC_API_KEY"), }, + + xai = { + endpoint = "https://api.x.ai/v1/chat/completions", + secret = os.getenv("XAI_API_KEY"), + }, }, ``` diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 22d2ce8..8a6f0b0 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -72,6 +72,11 @@ local config = { endpoint = "https://api.anthropic.com/v1/messages", secret = os.getenv("ANTHROPIC_API_KEY"), }, + xai = { + disable = true, + endpoint = "https://api.x.ai/v1/chat/completions", + secret = os.getenv("XAI_API_KEY"), + }, }, -- prefix for all commands @@ -310,6 +315,15 @@ local config = { model = { model = "claude-3-5-haiku-latest", temperature = 0.8, top_p = 1 }, system_prompt = require("gp.defaults").code_system_prompt, }, + { + provider = "xai", + name = "Grok-4", + chat = false, + command = true, + -- string with model name or table with model name and parameters + model = { model = "grok-4-latest", temperature = 0 }, + system_prompt = require("gp.defaults").code_system_prompt, + }, { provider = "ollama", name = "CodeOllamaLlama3.1-8B", diff --git a/lua/gp/dispatcher.lua b/lua/gp/dispatcher.lua index c28caba..b5f4b71 100644 --- a/lua/gp/dispatcher.lua +++ b/lua/gp/dispatcher.lua @@ -169,6 +169,30 @@ D.prepare_payload = function(messages, model, provider) return payload end + if provider == "xai" then + local system = "" + local i = 1 + while i < #messages do + if messages[i].role == "system" then + system = system .. messages[i].content .. "\n" + table.remove(messages, i) + else + i = i + 1 + end + end + + local payload = { + model = model.model, + stream = true, + messages = messages, + system = system, + max_tokens = model.max_tokens or 4096, + temperature = math.max(0, math.min(2, model.temperature or 1)), + top_p = math.max(0, math.min(1, model.top_p or 1)), + } + return payload + end + if provider == "ollama" then local payload = { model = model.model, @@ -452,6 +476,14 @@ local query = function(buf, provider, payload, handler, on_exit, callback) "api-key: " .. bearer, } endpoint = render.template_replace(endpoint, "{{model}}", payload.model) + elseif provider == "xai" then + -- currently xai only uses bearer token for authentication. + -- since I cannot sure its going to be that way for long time + -- branching out as another condition. + headers = { + "-H", + "Authorization: Bearer " .. bearer, + } elseif provider == "ollama" then headers = {} else -- default to openai compatible headers