{"id":18234354,"url":"https://github.com/kennethreitz/simplemind","last_synced_at":"2025-05-15T18:09:03.231Z","repository":{"id":259860590,"uuid":"879657839","full_name":"kennethreitz/simplemind","owner":"kennethreitz","description":"Python API client for AI providers that intends to replace LangChain and LangGraph for most common use cases.","archived":false,"fork":false,"pushed_at":"2025-02-09T00:14:40.000Z","size":2125,"stargazers_count":491,"open_issues_count":9,"forks_count":25,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-04-03T05:09:33.500Z","etag":null,"topics":["ai","anthropic","anthropic-claude","api-client","artificial-intelligence","gemini","langchain","llms","openai","openai-api"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/simplemind/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kennethreitz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"kennethreitz","thanks_dev":"kennethreitz","custom":"https://cash.app/$KennethReitz"}},"created_at":"2024-10-28T10:16:23.000Z","updated_at":"2025-04-01T09:22:43.000Z","dependencies_parsed_at":"2024-10-28T13:41:53.544Z","dependency_job_id":"2ebc7d99-b269-48a4-8d7b-3d03c1c2abbe","html_url":"https://github.com/kennethreitz/simplemind","commit_stats":null,"previous_names":["kennethreitz/simplemind"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennethreitz%2Fsimplemind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennethreitz%2Fsimplemind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennethreitz%2Fsimplemind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kennethreitz%2Fsimplemind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kennethreitz","download_url":"https://codeload.github.com/kennethreitz/simplemind/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248489276,"owners_count":21112540,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","anthropic","anthropic-claude","api-client","artificial-intelligence","gemini","langchain","llms","openai","openai-api"],"created_at":"2024-11-04T21:09:31.070Z","updated_at":"2025-04-11T22:29:35.887Z","avatar_url":"https://github.com/kennethreitz.png","language":"Python","funding_links":["https://github.com/sponsors/kennethreitz","https://thanks.dev/kennethreitz","https://cash.app/$KennethReitz"],"categories":["Python"],"sub_categories":[],"readme":"# Simplemind: AI for Humans™\n\n**Keep it simple, keep it human.**\n\nSimplemind is 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.\n\n![simplemind](https://github.com/user-attachments/assets/36df2103-2583-4958-ad5e-19cda7740256)\n\n## Features\n\nWith Simplemind, tapping into AI is as easy as a friendly conversation.\n\n- **Easy-to-use AI tools**: Simplemind provides simple interfaces to most popular AI services.\n- **Human-centered design**: The library prioritizes readability and usability—no need to be an expert to start experimenting.\n- **Minimal configuration**: Get started quickly, without worrying about configuration headaches.\n\n## Supported APIs\n\nThe APIs remain identical between all supported providers / models:\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003e\u003c/th\u003e\n      \u003cth\u003e\u003ccode\u003ellm_provider\u003c/code\u003e\u003c/th\u003e\n      \u003cth\u003eDefault \u003ccode\u003ellm_model\u003c/code\u003e\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://www.anthropic.com/claude\"\u003eAnthropic's Claude\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"anthropic\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"claude-3-5-sonnet-20241022\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://aws.amazon.com/bedrock/\"\u003eAmazon's Bedrock\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"amazon\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"anthropic.claude-3-5-sonnet-20241022-v2:0\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://www.deepseek.com\"\u003eDeepseek\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"deepseek\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"deepseek-chat\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://gemini.google/\"\u003eGoogle's Gemini\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"gemini\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"models/gemini-1.5-pro\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://groq.com/\"\u003eGroq's Groq\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"groq\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"llama3-8b-8192\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://ollama.com\"\u003eOllama\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"ollama\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"llama3.2\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://openai.com/gpt\"\u003eOpenAI's GPT\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"openai\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"gpt-4o-mini\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\u003ca href=\"https://x.ai/\"\u003exAI's Grok\u003c/a\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"xai\"\u003c/code\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003ccode\u003e\"grok-beta\"\u003c/code\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\nTo 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`.\n\nIf you want to see Simplemind support additional providers or models, please send a pull request!\n\n## Quickstart\n\nSimplemind takes care of the complex API calls so you can focus on what matters—building, experimenting, and creating.\n\n```bash\n$ pip install 'simplemind[full]'\n```\n\nFirst, authenticate your API keys by setting them in the environment variables:\n\n```bash\n$ export OPENAI_API_KEY=\"sk-...\"\n```\n\nThis pattern allows you to keep your API keys private and out of your codebase. Other supported environment variables: `ANTHROPIC_API_KEY`, `XAI_API_KEY`, `DEEPSEEK_API_KEY`, `GROQ_API_KEY`, and `GEMINI_API_KEY`.\n\nNext, import Simplemind and start using it:\n\n```python\nimport simplemind as sm\n```\n\n## Examples\n\nHere are some examples of how to use Simplemind.\n\n**Please note**: Most of the calls seen here optionally accept `llm_provider` and `llm_model` parameters, which you provide as strings.\n\n### Text Completion\n\nGenerate a response from an AI model based on a given prompt:\n\n```pycon\n\u003e\u003e\u003e sm.generate_text(prompt=\"What is the meaning of life?\")\n\"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 life’s 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.\"\n```\n\n### Streaming Text\n\n```python\n\u003e\u003e\u003e for chunk in sm.generate_text(\"Write a poem about the moon\", stream=True):\n...     print(chunk, end=\"\", flush=True)\n```\n\n### Structured Data with Pydantic\n\nYou can use Pydantic models to structure the response from the LLM, if the LLM supports it.\n\n```python\nclass Poem(BaseModel):\n    title: str\n    content: str\n```\n\n```pycon\n\u003e\u003e\u003e sm.generate_data(\"Write a poem about love\", response_model=Poem)\ntitle='Eternal Embrace' content='In the quiet hours of the night,\\nWhen stars whisper secrets bright,\\nTwo hearts beat in a gentle rhyme,\\nDancing through the sands of time.\\n\\nWith every glance, a spark ignites,\\nA flame that warms the coldest nights,\\nIn laughter shared and whispers sweet,\\nLove paints the world, a masterpiece.\\n\\nThrough stormy skies and sunlit days,\\nIn myriad forms, it finds its ways,\\nA tender touch, a knowing sigh,\\nIn love’s embrace, we learn to fly.\\n\\nAs seasons change and moments fade,\\nIn the tapestry of dreams we’ve laid,\\nLove’s threads endure, forever bind,\\nA timeless bond, two souls aligned.\\n\\nSo here’s to love, both bright and true,\\nA gift we give, anew, anew,\\nIn every heartbeat, every prayer,\\nA story written in the air.'\n```\n\n#### A more complex example\n\n```python\nclass InstructionStep(BaseModel):\n    step_number: int\n    instruction: str\n\nclass RecipeIngredient(BaseModel):\n    name: str\n    quantity: float\n    unit: str\n\nclass Recipe(BaseModel):\n    name: str\n    ingredients: list[RecipeIngredient]\n    instructions: list[InstructionStep]\n\nrecipe = sm.generate_data(\n    \"Write a recipe for chocolate chip cookies\",\n    response_model=Recipe,\n)\n```\n\nSpecial thanks to [@jxnl](https://github.com/jxnl) for building [Instructor](https://github.com/jxnl/instructor), which makes this possible!\n\n### Conversational AI\n\nSimpleMind also allows for easy conversational flows:\n\n```pycon\n\u003e\u003e\u003e conv = sm.create_conversation()\n\n\u003e\u003e\u003e # Add a message to the conversation\n\u003e\u003e\u003e conv.add_message(\"user\", \"Hi there, how are you?\")\n\n\u003e\u003e\u003e conv.send()\n\u003cMessage role=assistant text=\"Hello! I'm just a computer program, so I don't have feelings, but I'm here and ready to help you. How can I assist you today?\"\u003e\n```\n\nTo continue the conversation, you can call `conv.send()` again, which returns the next message in the conversation:\n\n```pycon\n\u003e\u003e\u003e conv.add_message(\"user\", \"What is the meaning of life?\")\n\u003e\u003e\u003e conv.send()\n\u003cMessage role=assistant text=\"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 life’s 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.\"\u003e\n```\n\n### Stop Repeating Yourself\n\nYou can use the `Session` class to set default parameters for all calls:\n\n```python\n# Create a session with defaults\ngpt_4o_mini = sm.Session(llm_provider=\"openai\", llm_model=\"gpt-4o-mini\")\n\n# Now all calls use these defaults\nresponse = gpt_4o_mini.generate_text(\"Hello!\")\nconversation = gpt_4o_mini.create_conversation()\n```\n\nThis maintains the simplicity of the original API while reducing repetition.\n\nThe session object also supports overriding defaults on a per-call basis:\n\n```python\nresponse = gpt_4o_mini.generate_text(\"Complex task here\", llm_model=\"gpt-4\")\n```\n\n### Basic Memory Plugin\n\nHarnessing the power of Python, you can easily create your own plugins to add additional functionality to your conversations:\n\n```python\nclass SimpleMemoryPlugin(sm.BasePlugin):\n    def __init__(self):\n        self.memories = [\n            \"the earth has fictionally beeen destroyed.\",\n            \"the moon is made of cheese.\",\n        ]\n\n    def yield_memories(self):\n        return (m for m in self.memories)\n\n    def pre_send_hook(self, conversation: sm.Conversation):\n        for m in self.yield_memories():\n            conversation.add_message(role=\"system\", text=m)\n\n\nconversation = sm.create_conversation()\nconversation.add_plugin(SimpleMemoryPlugin())\n\n\nconversation.add_message(\n    role=\"user\",\n    text=\"Please write a poem about the moon\",\n)\n```\n\n```pycon\n\u003e\u003e\u003e conversation.send()\nIn the vast expanse where stars do play,\nThere orbits a cheese wheel, far away.\nIt's not of stone or silver hue,\nBut cheddar's glow, a sight anew.\n\nIn cosmic silence, it does roam,\nA lonely traveler, away from home.\nNo longer does it reflect the sun,\nBut now it's known for fun begun.\n\nOnce Earth's companion, now alone,\nA cheese moon orbits, in the dark it's thrown.\nIts surface, not of craters wide,\nBut gouda, swiss, and camembert's pride.\n\nAstronauts of yore, they sought its face,\nTo find the moon was not a place,\nBut a haven of dairy delight,\nGlowing softly through the night.\n\nIn this world, where cheese takes flight,\nThe moon brings laughter, a whimsical sight.\nNo longer just a silent sphere,\nBut a beacon of joy, far and near.\n\nSo here's to the moon, in cheese attire,\nA playful twist in the cosmic choir.\nA reminder that in tales and fun,\nThe universe is never done.\n```\n\nSimple, yet effective.\n\n### Tools (Function calling)\nTools (also known as functions) let you call any Python function from your AI conversations. Here's an example:\n\n```python\ndef get_weather(\n    location: Annotated[\n        str, Field(description=\"The city and state, e.g. San Francisco, CA\")\n    ],\n    unit: Annotated[\n        Literal[\"celcius\", \"fahrenheit\"],\n        Field(\n            description=\"The unit of temperature, either 'celsius' or 'fahrenheit'\"\n        ),\n    ] = \"celcius\",\n):\n    \"\"\"\n    Get the current weather in a given location\n    \"\"\"\n    return f\"42 {unit}\"\n\n# Add your function as a tool\nconversation = sm.create_conversation()\nconversation.add_message(\"user\", \"What's the weather in San Francisco?\")\nresponse = conversation.send(tools=[get_weather])\n```\n\nNote how we're using Python's `Annotated` feature combined with `Field` to provide additional context to our function parameters. This helps the AI understand the intention and constraints of each parameter, making tool calls more accurate and reliable.\nYou can alos ommit `Annotated` and just pass the `Field` parameter.\n```python\ndef get_weather(\n    location: str = Field(description=\"The city and state, e.g. San Francisco, CA\"),\n    unit:Literal[\"celcius\", \"fahrenheit\"]= Field(\n        default=\"celcius\",\n        description=\"The unit of temperature, either 'celsius' or 'fahrenheit'\"\n        ),\n):\n    \"\"\"\n    Get the current weather in a given location\n    \"\"\"\n    return f\"42 {unit}\"\n```\n\nFunctions can be defined with type hints and Pydantic models for validation. The LLM will intelligently choose when to call the functions and incorporate the results into its responses.\n\n#### 🪄 Using LLM for automatic tool definition (Experimental)\n\nSimplemind provides a decorator to automatically transform Python functions into tools with AI-generated metadata. Simply use the `@simplemind.tool` decorator to have the LLM analyze your function and generate appropriate descriptions and schema:\n\n```python\n@simplemind.tool(llm_provider=\"anthropic\")\ndef haversine(lat1: float, lon1: float, lat2: float, lon2: float) -\u003e float:\n    r = 6371\n    phi1 = math.radians(lat1)\n    phi2 = math.radians(lat2)\n    delta_phi = math.radians(lat2 - lat1)\n    delta_lambda = math.radians(lon2 - lon1)\n\n    a = (\n        math.sin(delta_phi / 2) ** 2\n        + math.cos(phi1) * math.cos(phi2) * math.sin(delta_lambda / 2) ** 2\n    )\n    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))\n    d = r * c\n    return d\n```\nNotice how we have not added any docstrings or `Field` for the function.\nThe decorator will use the specified LLM provider to generate the tool schema, including descriptions and parameter details:\n\n```json\n{\n    \"name\": \"haversine\",\n    \"description\": \"Calculates the great-circle distance between two points on Earth given their latitude and longitude coordinates\",\n    \"input_schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"lat1\": {\n                \"type\": \"number\",\n                \"description\": \"Latitude of the first point in decimal degrees\",\n            },\n            \"lon1\": {\n                \"type\": \"number\",\n                \"description\": \"Longitude of the first point in decimal degrees\",\n            },\n            \"lat2\": {\n                \"type\": \"number\",\n                \"description\": \"Latitude of the second point in decimal degrees\",\n            },\n            \"lon2\": {\n                \"type\": \"number\",\n                \"description\": \"Longitude of the second point in decimal degrees\",\n            }\n        },\n        \"required\": [\"lat1\", \"lon1\", \"lat2\", \"lon2\"],\n    },\n}\n```\n\nThe decorated function can then be used like any other tool with the conversation API.\n\n```python\nconversation = sm.create_conversation()\nconversation.add_message(\"user\", \"How far is London from my location\")\nresponse = conversation.send(tools=[get_location, get_coords, haversine]) # Multiple tools can be passed\n```\n\nSee [examples/distance_calculator.py](examples/distance_calculator.py) for more.\n\n### Logging\n\nSimplemind uses [Logfire](https://pydantic.dev/logfire) for logging. To enable logging, call `sm.enable_logfire()`.\n\n### More Examples\n\nPlease see the [examples](examples) directory for executable examples.\n\n---\n\n## Contributing\n\nWe welcome contributions of all kinds. Feel free to open issues for bug reports or feature requests, and submit pull requests to make SimpleMind even better.\n\nTo get started:\n\n1. Fork the repository.\n2. Create a new branch.\n3. Make your changes.\n4. Submit a pull request.\n\n## License\n\nSimplemind is licensed under the Apache 2.0 License.\n\n## Acknowledgements\n\nSimplemind 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkennethreitz%2Fsimplemind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkennethreitz%2Fsimplemind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkennethreitz%2Fsimplemind/lists"}