mirror of
https://github.com/kennethreitz/simplemind.git
synced 2026-06-05 22:50:18 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c8f22bef1 | |||
| 9c3f2a6df3 | |||
| febf5473d5 | |||
| 48ac97f070 | |||
| c41a3f00fb | |||
| 25ee4ae32c | |||
| 984721f02b | |||
| 69c8723770 | |||
| 0c10d5676a | |||
| e0ddf41e15 | |||
| f940ae2dfd | |||
| 85fa4f5879 | |||
| 44581e8fe3 | |||
| 9503ec7fd3 | |||
| 418f36dcc0 | |||
| bf9683cfd0 | |||
| 3909588f3e | |||
| 33d8f18bff | |||
| d7388ef0d5 | |||
| 02d10bfda9 | |||
| 5dc6e7b006 | |||
| 62933c8553 | |||
| f0a6be73f8 | |||
| 9257a04f34 | |||
| 64dbe9a2e7 | |||
| ccb8311089 | |||
| 0c29380501 | |||
| 7b43208a03 | |||
| e931fd0eae | |||
| 736d942527 |
@@ -167,3 +167,4 @@ cython_debug/
|
||||
|
||||
src/**
|
||||
requirements.txt
|
||||
Pipfile
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
Release History
|
||||
===============
|
||||
|
||||
## 0.1.6 (2024-10-31)
|
||||
|
||||
- Add `sm.Plugin` syntax sugar.
|
||||
- Improvements to Anthropic provider, related to max tokens.
|
||||
- General improvements.
|
||||
- Add tests for structured response.
|
||||
- Add `llm_model` to `structured_response`.
|
||||
|
||||
## 0.1.5 (2024-10-31)
|
||||
|
||||
- Add Gemini provider.
|
||||
- Add structured response to Gemini provider.
|
||||
- Support for Python 3.10.
|
||||
|
||||
## 0.1.4 (2024-10-30)
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ Simplemind is AI library designed to simplify your experience with AI APIs in Py
|
||||
|
||||

|
||||
|
||||
[](https://mutable.ai/kennethreitz/simplemind)
|
||||
|
||||
## Features
|
||||
|
||||
With Simplemind, tapping into AI is as easy as a friendly conversation.
|
||||
@@ -18,7 +16,7 @@ With Simplemind, tapping into AI is as easy as a friendly conversation.
|
||||
|
||||
## Supported APIs
|
||||
|
||||
To specify a specific provider or model, you can use the `llm_provider` and `llm_model` parameters when calling: `generate_text`, `generate_data`, or `create_conversation`.
|
||||
To specify a specific provider or model, you can use the `llm_provider` and `llm_model` parameters when calling: `generate_text`, `generate_data`, or `create_conversation`. The APIs remain identital between all supported providers/models.
|
||||
|
||||
- [**Anthropic's Claude**](https://www.anthropic.com/claude)
|
||||
- [**Google's Gemini**](https://gemini.google/)
|
||||
@@ -27,7 +25,7 @@ To specify a specific provider or model, you can use the `llm_provider` and `llm
|
||||
- [**OpenAI's GPT**](https://openai.com/gpt)
|
||||
- [**xAI's Grok**](https://x.ai/)
|
||||
|
||||
If you want to see Simplemind support, additional providers or models, please request a pull!
|
||||
If you want to see Simplemind support, additional providers or models, please send a pull request!
|
||||
|
||||
## Why SimpleMind?
|
||||
- **Intuitive**: Built with Pythonic simplicity and readability in mind.
|
||||
@@ -50,7 +48,7 @@ First, authenticate your API keys by setting them in the environment variables:
|
||||
$ export OPENAI_API_KEY="sk-..."
|
||||
```
|
||||
|
||||
This pattern allows you to keep your API keys private and out of your codebase. Other supported environment variables: `ANTHROPIC_API_KEY`, `XAI_API_KEY`, and `GROQ_API_KEY`.
|
||||
This pattern allows you to keep your API keys private and out of your codebase. Other supported environment variables: `ANTHROPIC_API_KEY`, `XAI_API_KEY`, `GROQ_API_KEY`, and `GEMINI_API_KEY`.
|
||||
|
||||
Next, import Simplemind and start using it:
|
||||
|
||||
@@ -219,3 +217,4 @@ Simplemind is licensed under the Apache 2.0 License.
|
||||
|
||||
## Acknowledgements
|
||||
Simplemind is inspired by the philosophy of "code for humans" and aims to make working with AI models accessible to all. Special thanks to the open-source community for their contributions and inspiration.
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import simplemind
|
||||
project = "simplemind"
|
||||
copyright = "2024 Kenneth Reitz"
|
||||
author = "Kenneth Reitz"
|
||||
release = "v0.1.5"
|
||||
release = "v0.1.6"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "simplemind"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
description = "An experimental client for AI providers that intends to replace LangChain and LangGraph for most common use cases."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@@ -16,7 +16,7 @@ class Session:
|
||||
self,
|
||||
*,
|
||||
llm_provider: str = settings.DEFAULT_LLM_PROVIDER,
|
||||
llm_model: str = settings.DEFAULT_LLM_MODEL,
|
||||
llm_model: str | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
self.llm_provider = llm_provider
|
||||
@@ -113,6 +113,9 @@ def generate_text(
|
||||
return provider.generate_text(prompt=prompt, llm_model=llm_model, **kwargs)
|
||||
|
||||
|
||||
# Syntax sugar.
|
||||
Plugin = BasePlugin
|
||||
|
||||
__all__ = [
|
||||
"create_conversation",
|
||||
"find_provider",
|
||||
@@ -121,4 +124,5 @@ __all__ = [
|
||||
"settings",
|
||||
"BasePlugin",
|
||||
"Session",
|
||||
"Plugin",
|
||||
]
|
||||
|
||||
@@ -13,12 +13,14 @@ T = TypeVar("T", bound=BaseModel)
|
||||
|
||||
PROVIDER_NAME = "anthropic"
|
||||
DEFAULT_MODEL = "claude-3-5-sonnet-20241022"
|
||||
DEFAULT_MAX_TOKENS = 1000
|
||||
DEFAULT_MAX_TOKENS = 1_000
|
||||
DEFAULT_KWARGS = {"max_tokens": DEFAULT_MAX_TOKENS}
|
||||
|
||||
|
||||
class Anthropic(BaseProvider):
|
||||
NAME = PROVIDER_NAME
|
||||
DEFAULT_MODEL = DEFAULT_MODEL
|
||||
DEFAULT_KWARGS = DEFAULT_KWARGS
|
||||
|
||||
def __init__(self, api_key: str | None = None):
|
||||
self.api_key = api_key or settings.get_api_key(PROVIDER_NAME)
|
||||
@@ -46,8 +48,7 @@ class Anthropic(BaseProvider):
|
||||
response = self.client.messages.create(
|
||||
model=conversation.llm_model or self.DEFAULT_MODEL,
|
||||
messages=messages,
|
||||
max_tokens=DEFAULT_MAX_TOKENS,
|
||||
**kwargs,
|
||||
**{**self.DEFAULT_KWARGS, **kwargs},
|
||||
)
|
||||
|
||||
# Get the response content from the Anthropic response
|
||||
@@ -62,9 +63,22 @@ class Anthropic(BaseProvider):
|
||||
llm_provider=PROVIDER_NAME,
|
||||
)
|
||||
|
||||
def structured_response(self, model: str, response_model: Type[T], **kwargs) -> T:
|
||||
def structured_response(
|
||||
self, response_model: Type[T], *, llm_model: str | None = None, **kwargs
|
||||
) -> T:
|
||||
model = llm_model or self.DEFAULT_MODEL
|
||||
|
||||
# Extract the prompt from kwargs if it exists
|
||||
prompt = kwargs.pop("prompt", kwargs.pop("messages", ""))
|
||||
|
||||
# Format the messages properly
|
||||
messages = [{"role": "user", "content": prompt}]
|
||||
|
||||
response = self.structured_client.messages.create(
|
||||
model=model or self.DEFAULT_MODEL, response_model=response_model, **kwargs
|
||||
model=model,
|
||||
messages=messages, # Add the messages parameter
|
||||
response_model=response_model,
|
||||
**{**self.DEFAULT_KWARGS, **kwargs},
|
||||
)
|
||||
return response
|
||||
|
||||
@@ -76,8 +90,7 @@ class Anthropic(BaseProvider):
|
||||
response = self.client.messages.create(
|
||||
model=llm_model or self.DEFAULT_MODEL,
|
||||
messages=messages,
|
||||
max_tokens=DEFAULT_MAX_TOKENS,
|
||||
**kwargs,
|
||||
**{**self.DEFAULT_KWARGS, **kwargs},
|
||||
)
|
||||
|
||||
return response.content[0].text
|
||||
|
||||
@@ -72,6 +72,7 @@ class Groq(BaseProvider):
|
||||
response = self.structured_client.chat.completions.create(
|
||||
messages=messages,
|
||||
response_model=response_model,
|
||||
model=kwargs.pop("llm_model", self.DEFAULT_MODEL),
|
||||
**kwargs,
|
||||
)
|
||||
return response
|
||||
|
||||
@@ -65,7 +65,12 @@ class Ollama(BaseProvider):
|
||||
)
|
||||
|
||||
def structured_response(
|
||||
self, prompt: str, response_model: Type[T], *, llm_model: str, **kwargs
|
||||
self,
|
||||
prompt: str,
|
||||
response_model: Type[T],
|
||||
*,
|
||||
llm_model: str | None = None,
|
||||
**kwargs,
|
||||
) -> T:
|
||||
"""Get a structured response from the Ollama API."""
|
||||
messages = [
|
||||
@@ -80,7 +85,7 @@ class Ollama(BaseProvider):
|
||||
)
|
||||
return response
|
||||
|
||||
def generate_text(self, prompt: str, *, llm_model: str) -> str:
|
||||
def generate_text(self, prompt: str, *, llm_model: str | None = None) -> str:
|
||||
"""Generate text using the Ollama API."""
|
||||
messages = [
|
||||
{"role": "user", "content": prompt},
|
||||
|
||||
@@ -29,7 +29,6 @@ class Settings(BaseSettings):
|
||||
)
|
||||
XAI_API_KEY: Optional[SecretStr] = Field(None, description="API key for xAI")
|
||||
DEFAULT_LLM_PROVIDER: str = Field("openai", description="The default LLM provider")
|
||||
DEFAULT_LLM_MODEL: str = Field("gpt-4o-mini", description="The default LLM model")
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env", env_file_encoding="utf-8", case_sensitive=True, extra="ignore"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import pytest
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Add the project root to the Python path.
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from simplemind import Session
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sm():
|
||||
"""Fixture that provides a simplemind Session instance with default settings."""
|
||||
return Session()
|
||||
@@ -0,0 +1,2 @@
|
||||
def test_basic_math():
|
||||
assert 1 + 1 == 2
|
||||
@@ -0,0 +1,28 @@
|
||||
import pytest
|
||||
|
||||
from simplemind.providers import Anthropic, Gemini, OpenAI, Groq, Ollama
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ResponseModel(BaseModel):
|
||||
result: int
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"provider_cls",
|
||||
[
|
||||
Anthropic,
|
||||
Gemini,
|
||||
OpenAI,
|
||||
Groq,
|
||||
Ollama,
|
||||
],
|
||||
)
|
||||
def test_generate_data(provider_cls):
|
||||
provider = provider_cls()
|
||||
prompt = "What is 2+2?"
|
||||
|
||||
data = provider.structured_response(prompt=prompt, response_model=ResponseModel)
|
||||
|
||||
assert isinstance(data, ResponseModel)
|
||||
assert type(data.result) == int
|
||||
@@ -0,0 +1,23 @@
|
||||
import pytest
|
||||
|
||||
from simplemind.providers import Anthropic, Gemini, OpenAI, Groq, Ollama
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"provider_cls",
|
||||
[
|
||||
Anthropic,
|
||||
Gemini,
|
||||
OpenAI,
|
||||
Groq,
|
||||
Ollama,
|
||||
],
|
||||
)
|
||||
def test_generate_text(provider_cls):
|
||||
provider = provider_cls()
|
||||
prompt = "What is 2+2?"
|
||||
|
||||
response = provider.generate_text(prompt=prompt, llm_model=provider.DEFAULT_MODEL)
|
||||
|
||||
assert isinstance(response, str)
|
||||
assert len(response) > 0
|
||||
Reference in New Issue
Block a user