-
Notifications
You must be signed in to change notification settings - Fork 10
Support provider-specific API key configuration #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,76 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from langchain_core.language_models.chat_models import BaseChatModel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def create_llm( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url: str | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> BaseChatModel: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Factory function to create a LangChain chat model. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parameters | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ---------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider : str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LLM provider name. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model : str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Model name. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key : str | None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Optional API key. Falls back to environment variable. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url : str | None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Optional base URL for OpenAI-compatible APIs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider = provider.lower() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if provider == "groq": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from langchain_groq import ChatGroq | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ChatGroq( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model=model, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key=api_key or os.getenv("GROQ_API_KEY"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif provider in ("google", "gemini"): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from langchain_google_genai import ChatGoogleGenerativeAI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ChatGoogleGenerativeAI( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model=model, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| google_api_key=api_key or os.getenv("GOOGLE_API_KEY"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif provider == "openai": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from langchain_openai import ChatOpenAI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ChatOpenAI( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model=model, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key=api_key or os.getenv("OPENAI_API_KEY"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url=base_url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif provider == "anthropic": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from langchain_anthropic import ChatAnthropic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ChatAnthropic( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model=model, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key=api_key or os.getenv("ANTHROPIC_API_KEY"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif provider == "openrouter": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from langchain_openai import ChatOpenAI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ChatOpenAI( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model=model, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key=api_key or os.getenv("OPENROUTER_API_KEY"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| base_url=base_url or "https://openrouter.ai/api/v1", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Unsupported provider '{provider}'." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+64
to
+76
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Missing "together" provider creates cross-file inconsistency.
🔧 Proposed fix: add "together" provider support elif provider == "openrouter":
return ChatOpenAI(
model=model,
api_key=api_key or os.getenv("OPENROUTER_API_KEY"),
base_url=base_url or "https://openrouter.ai/api/v1",
**kwargs,
)
+ elif provider == "together":
+ return ChatOpenAI(
+ model=model,
+ api_key=api_key or os.getenv("TOGETHER_API_KEY"),
+ base_url=base_url or "https://api.together.xyz/v1",
+ **kwargs,
+ )
+
else:
raise ValueError(
f"Unsupported provider '{provider}'."
)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Validate non-empty API key before persisting.
input(...).strip()returns an empty string if the user presses Enter. The empty key is saved to the env file and returned, causing confusing authentication errors downstream with no clear root cause.🛡️ Proposed fix: reject empty input
rprint(f"[yellow]{provider} API key is missing![/yellow]\n") api_key = input(f"Enter your {provider} API key: ").strip() + if not api_key: + rprint("[red]API key cannot be empty. Aborting.[/red]") + raise ValueError("API key cannot be empty") + env[env_var] = api_key save_env(env)📝 Committable suggestion
🤖 Prompt for AI Agents