47 Commits

Author SHA1 Message Date
kennethreitz d4cfce01ba Update OLLAMA_HOST_URL default value 2024-10-29 16:24:02 -04:00
kennethreitz da9958ef46 Update README.md 2024-10-29 16:22:43 -04:00
kennethreitz 918705e2d5 Add ollama provider and update version to 0.1.2 2024-10-29 16:19:25 -04:00
kennethreitz eae68d1ee1 Merge branch 'ollama' 2024-10-29 16:18:25 -04:00
kennethreitz 3dccac85ff Refactor Ollama provider to use default timeout and add support for structured responses 2024-10-29 16:18:02 -04:00
kennethreitz 4f3fcac02d Refactor generate_data.py to use correct conversation setup and formatting 2024-10-29 16:08:26 -04:00
kennethreitz 593d6c8e07 proper manners 2024-10-29 16:08:26 -04:00
kennethreitz dd2b08b4cf Refactor generate_data.py to use correct conversation setup and formatting 2024-10-29 16:08:26 -04:00
kennethreitz 0fa4b60412 ask nicely 2024-10-29 16:08:26 -04:00
kennethreitz c1115ccf47 Refactor translate_to_french function to use the correct conversation setup 2024-10-29 16:08:26 -04:00
kennethreitz 0100ad0163 Refactor translate_to_french function to use the correct conversation setup 2024-10-29 16:08:26 -04:00
kennethreitz 3090ade9e3 Fix Groq provider in CHANGELOG.md and update version in pyproject.toml 2024-10-29 16:08:26 -04:00
kennethreitz 3e2801a1ac Refactor Groq provider to use the correct client method 2024-10-29 16:08:26 -04:00
Kurt Heiden d9f0d21e53 Update README.md 2024-10-29 13:48:52 -06:00
kennethreitz 5bf4fc81e7 Refactor generate_data.py to use correct conversation setup and formatting 2024-10-29 14:29:50 -04:00
kennethreitz ca0246a3bb proper manners 2024-10-29 12:37:26 -04:00
kennethreitz 30885beda7 Refactor generate_data.py to use correct conversation setup and formatting 2024-10-29 12:36:13 -04:00
kennethreitz a1dfe65084 ask nicely 2024-10-29 12:35:37 -04:00
kennethreitz 641de59138 Refactor translate_to_french function to use the correct conversation setup 2024-10-29 12:19:29 -04:00
kennethreitz 3c4ed48786 Refactor translate_to_french function to use the correct conversation setup 2024-10-29 12:18:55 -04:00
kennethreitz 467f67d283 Fix Groq provider in CHANGELOG.md and update version in pyproject.toml 2024-10-29 12:18:55 -04:00
kennethreitz b109964340 Refactor Groq provider to use the correct client method 2024-10-29 12:18:55 -04:00
Kurt Heiden b04c68f57d Remove docker components 2024-10-29 09:37:48 -06:00
Kurt Heiden 8ed065836a Update ollama.py 2024-10-29 08:44:19 -06:00
Kurt Heiden abdac66fee Update test_ollama.py 2024-10-29 08:42:29 -06:00
Kurt Heiden 1ce2759564 Update settings.py 2024-10-29 08:29:29 -06:00
Kurt Heiden d0a76d7532 Update ollama.py 2024-10-29 08:29:26 -06:00
Kurt Heiden 846efb4190 Merge branch 'main' into ollama-update 2024-10-29 08:09:03 -06:00
kennethreitz 24b8aa1868 Delete Dockerfile 2024-10-29 07:40:28 -04:00
kennethreitz eab6730372 Delete docker-compose.yaml 2024-10-29 07:40:20 -04:00
kennethreitz 2a8b0f07f9 Add CHANGELOG.md with initial release history 2024-10-29 07:37:32 -04:00
kennethreitz 225c187b19 Update README.md 2024-10-29 07:36:57 -04:00
kennethreitz a7bc7cee1d Update README.md with Pydantic model for structured data 2024-10-29 07:35:05 -04:00
kennethreitz 031b154648 test 2024-10-29 07:33:42 -04:00
kennethreitz 52f0084ac8 test 2024-10-29 07:33:22 -04:00
kennethreitz 62a68aafc6 test 2024-10-29 07:32:20 -04:00
kennethreitz 462e45612d update links on readme 2024-10-29 07:31:42 -04:00
kennethreitz 9a5ad78a3f Update README.md 2024-10-29 07:30:32 -04:00
kennethreitz 42da9bcc87 Update README.md 2024-10-29 07:30:16 -04:00
Kurt Heiden dcb9c14d30 Update simplemind/models.py
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-10-28 22:05:55 -06:00
Kurt Heiden 87d636ca55 Update README.md
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-10-28 22:00:29 -06:00
Kurt Heiden 83d430a310 Update test_ollama.py
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-10-28 21:59:36 -06:00
Kurt Heiden b23f732d55 Merge branch 'main' into ollama-update 2024-10-28 21:56:24 -06:00
Kurt Heiden 4c8cb49a58 Update test_ollama.py 2024-10-28 21:46:52 -06:00
Kurt Heiden fb2460f907 prepend system memories for plugin 2024-10-28 21:45:25 -06:00
Kurt Heiden cb6d5540cb Update README.md 2024-10-28 21:22:59 -06:00
Kurt Heiden 23389c3a62 Add back Ollama integration 2024-10-28 21:22:15 -06:00
15 changed files with 155 additions and 64 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
export OPENAI_API_KEY=""
export ANTHROPIC_API_KEY=""
export XAI_API_KEY=""
export GROQ_API_KEY=""
export OLLAMA_HOST_URL=""
export GROQ_API_KEY=""
+1
View File
@@ -166,3 +166,4 @@ cython_debug/
.env
src/**
requirements.txt
+14
View File
@@ -0,0 +1,14 @@
Release History
===============
## 0.1.2 (2024-10-29)
- Add ollama provider.
## 0.1.1 (2024-10-29)
- Fix Groq provider.
## 0.1.0 (2024-10-29)
- Initial release.
-12
View File
@@ -1,12 +0,0 @@
FROM python:3.12.0
RUN apt-get update -y && apt-get upgrade -y
RUN pip install --upgrade pip
COPY requirements.txt /src/requirements.txt
WORKDIR /src
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "build.py"]
+20 -26
View File
@@ -4,6 +4,10 @@
SimpleMind is an AI library designed to simplify your experience with AI APIs in Python. Inspired by a "for humans" philosophy, it abstracts away complexity, giving developers an intuitive and human-friendly way to interact with powerful AI capabilities. With SimpleMind, tapping into AI is as easy as a friendly conversation.
```bash
$ pip install simplemind
```
## Features
- **Easy-to-use AI tools**: SimpleMind provides simple interfaces to popular AI services.
- **Human-centered design**: The library prioritizes readability and usability—no need to be an expert to start experimenting.
@@ -11,44 +15,39 @@ SimpleMind is an AI library designed to simplify your experience with AI APIs in
## Supported APIs
- **OpenAI's GPT**
- **Anthropic's Claude**
- **xAI's Grok**
- **Groq's Groq**
- **Ollama's Ollama**
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`.
- **[OpenAI's GPT](https://openai.com/gpt)**
- **[Anthropic's Claude](https://www.anthropic.com/claude)**
- **[xAI's Grok](https://x.ai/)**
- **[Groq's Groq](https://groq.com/)**
- **[Ollama](https://ollama.com)**
If you'd like to see SimpleMind support additional providers or models, please send a pull request!
## Why SimpleMind?
- **Intuitive**: Built with Pythonic simplicity and readability in mind.
- **For Humans**: Emphasizes a human-friendly interface, just like `requests` for HTTP.
- **Open Source**: SimpleMind is open source, and contributions are always welcome!
## Installation
Coming soon!
```bash
$ pip install simplemind
```
## Quickstart
SimpleMind takes care of the complex API calls so you can focus on what matters—building, experimenting, and creating.
```python
import simplemind as sm
```
Authenticate your API keys by setting them in the environment variables:
First, authenticate your API keys by setting them in the environment variables:
```bash
$ export OPENAI_API_KEY="sk-..."
```
Other supported environment variables: `ANTHROPIC_API_KEY`, `GROK_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`, `GROK_API_KEY`, `XAI_API_KEY`, and `GROQ_API_KEY`.
Next, import SimpleMind and start using it:
```python
import simplemind as sm
```
## Examples
@@ -64,7 +63,7 @@ Generate a response from an AI model based on a given prompt:
"The meaning of life is a profound philosophical question that has been explored by cultures, religions, and philosophers for centuries. Different people and belief systems offer varying interpretations:\n\n1. **Religious Perspectives:** Many religions propose that the meaning of life is to fulfill a divine purpose, serve God, or reach an afterlife. For example, Christianity often emphasizes love, faith, and service to God and others as central to lifes meaning.\n\n2. **Philosophical Views:** Philosophers offer diverse answers. Existentialists like Jean-Paul Sartre argue that life has no inherent meaning, and it is up to individuals to create their own purpose. Others, like Aristotle, suggest that achieving eudaimonia (flourishing or happiness) through virtuous living is the key to a meaningful life.\n\n3. **Scientific and Secular Approaches:** Some people find meaning through understanding the natural world, contributing to human knowledge, or through personal accomplishments and happiness. They may view life's meaning as a product of connection, legacy, or the pursuit of knowledge and creativity.\n\n4. **Personal Perspective:** For many, the meaning of life is deeply personal, involving their relationships, passions, and goals. These individuals define life's purpose through experiences, connections, and the impact they have on others and the world.\n\nUltimately, the meaning of life is a subjective question, with each person finding their own answers based on their beliefs, experiences, and reflections."
```
### Structured Response
### Structured Data with Pydantic
You can use Pydantic models to structure the response from the LLM, if the LLM supports it.
@@ -135,7 +134,7 @@ conversation.add_plugin(SimpleMemoryPlugin())
conversation.add_message(
role="user",
text="Write a poem about the moon",
text="Please write a poem about the moon",
)
```
```pycon
@@ -183,11 +182,6 @@ To get started:
3. Make your changes.
4. Submit a pull request.
## Building
1. Clone the repository.
2. `cd` to the root directory.
3. Run `docker-compose up --build`
## License
SimpleMind is licensed under the Apache 2.0 License.
-10
View File
@@ -1,10 +0,0 @@
services:
simplemind:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./simplemind:/src/simplemind
- ./build.py:/src/build.py
env_file:
- .env
+20 -5
View File
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Iterator
from pydantic import BaseModel
@@ -9,21 +9,36 @@ class Movie(BaseModel):
title: str
year: int
class MovieCharecter(BaseModel):
name: str
actor: str
class MovieQuote(BaseModel):
quote: str
movie: Movie
charecter: MovieCharecter
class QuotesList(BaseModel):
quotes: List[MovieQuote]
theme: str
quotes = sm.generate_data(llm_provider="openai", llm_model="gpt-4o-mini", prompt="Generate 20 quotes from famous movies", response_model=QuotesList)
def gen_quotes(n=10) -> Iterator[MovieQuote]:
"""Generate a list of quotes from famous movies."""
for quote in quotes.quotes:
print(f"{quote.charecter.name} from {quote.movie.title} ({quote.movie.year}): {quote.quote!r}")
for q in sm.generate_data(
llm_provider="openai",
llm_model="gpt-4o-mini",
prompt=f"Generate {n} quotes from famous movies",
response_model=QuotesList,
).quotes:
yield q
if __name__ == "__main__":
for quote in gen_quotes(n=20):
print(
f"{quote.charecter.name} from {quote.movie.title} ({quote.movie.year}): {quote.quote!r}"
)
+1 -1
View File
@@ -21,7 +21,7 @@ conversation.add_plugin(SimpleMemoryPlugin())
conversation.add_message(
role="user",
text="Write a poem about the moon",
text="Please write a poem about the moon",
)
r = conversation.send()
+9 -5
View File
@@ -1,9 +1,13 @@
from _context import sm
conversation = sm.create_conversation(llm_model="gpt-4o", llm_provider="openai")
conversation.add_message(
"user", "Translate the following text to French: 'Hello, world!'"
)
def translate_to_french(text: str) -> str:
conversation = sm.create_conversation(llm_model="gpt-4o", llm_provider="openai")
print(conversation.send().text)
conversation.add_message(
"user", f"Translate the following text to French: {text!r}"
)
return conversation.send().text
print(translate_to_french("an omlette with cheese"))
+2 -2
View File
@@ -1,10 +1,10 @@
[project]
name = "simplemind"
version = "0.1.0"
version = "0.1.2"
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.11"
dependencies = ["pydantic", "pydantic-settings", "instructor", "openai", "anthropic", "groq"]
dependencies = ["pydantic", "pydantic-settings", "instructor", "openai", "anthropic", "ollama", "groq"]
[build-system]
requires = ["hatchling"]
+3
View File
@@ -60,6 +60,9 @@ class Conversation(SMBaseModel):
def __str__(self):
return f"<Conversation id={self.id!r}>"
def prepend_system_message(self, role: str, text: str, meta: Optional[Dict[str, Any]] = None):
self.messages = [Message(role=role, text=text, meta=meta or {})] + self.messages
def add_message(
self, role: MESSAGE_ROLE, text: str, meta: Optional[Dict[str, Any]] = None
):
+2 -1
View File
@@ -4,6 +4,7 @@ from simplemind.providers._base import BaseProvider
from simplemind.providers.anthropic import Anthropic
from simplemind.providers.groq import Groq
from simplemind.providers.openai import OpenAI
from simplemind.providers.ollama import Ollama
from simplemind.providers.xai import XAI
providers: List[Type[BaseProvider]] = [Anthropic, Groq, OpenAI, XAI]
providers: List[Type[BaseProvider]] = [Anthropic, Groq, OpenAI, Ollama, XAI]
+1 -1
View File
@@ -83,7 +83,7 @@ class Groq(BaseProvider):
{"role": "user", "content": prompt},
]
response = self.structured_client.chat.completions.create(
response = self.client.chat.completions.create(
messages=messages,
model=llm_model,
**kwargs,
+77
View File
@@ -0,0 +1,77 @@
import ollama as ol
import instructor
from openai import OpenAI
from ._base import BaseProvider
from ..settings import settings
PROVIDER_NAME = "ollama"
DEFAULT_MODEL = "llama3.2"
DEFAULT_TIMEOUT = 60
class Ollama(BaseProvider):
NAME = PROVIDER_NAME
DEFAULT_MODEL = DEFAULT_MODEL
TIMEOUT = DEFAULT_TIMEOUT
def __init__(self, host_url: str = None):
self.host_url = host_url or settings.OLLAMA_HOST_URL
@property
def client(self):
"""The raw Ollama client."""
if not self.host_url:
raise ValueError("No ollama host url provided")
return ol.Client(timeout=self.TIMEOUT, host=self.host_url)
@property
def structured_client(self):
"""A client patched with Instructor."""
return instructor.from_openai(
OpenAI(
base_url=f"{self.host_url}/v1",
api_key="ollama",
),
mode=instructor.Mode.JSON,
)
def send_conversation(self, conversation: "Conversation"):
"""Send a conversation to the Ollama API."""
from ..models import Message
messages = [
{"role": msg.role, "content": msg.text} for msg in conversation.messages
]
response = self.client.chat(
model=conversation.llm_model or DEFAULT_MODEL, messages=messages
)
assistant_message = response.get("message")
# Create and return a properly formatted Message instance
return Message(
role="assistant",
text=assistant_message.get("content"),
raw=response,
llm_model=conversation.llm_model or DEFAULT_MODEL,
llm_provider=PROVIDER_NAME,
)
def structured_response(self, prompt, response_model, *, llm_model: str, **kwargs):
messages = [
{"role": "user", "content": prompt},
]
response = self.structured_client.chat.completions.create(
messages=messages, model=llm_model, response_model=response_model, **kwargs
)
return response
def generate_text(self, prompt, *, llm_model):
messages = [
{"role": "user", "content": prompt},
]
response = self.client.chat(messages=messages, model=llm_model)
return response.get("message").get("content")
+3
View File
@@ -12,6 +12,9 @@ class Settings(BaseSettings):
)
GROQ_API_KEY: Optional[SecretStr] = Field(None, description="API key for Groq")
OPENAI_API_KEY: Optional[SecretStr] = Field(None, description="API key for OpenAI")
OLLAMA_HOST_URL: Optional[str] = Field(
"http://127.0.0.1:11434", description="Fully qualified host URL for Ollama"
)
XAI_API_KEY: Optional[SecretStr] = Field(None, description="API key for xAI")
DEFAULT_LLM_PROVIDER: str = Field("openai", description="The default LLM provider")