Skip to content

Commit

Permalink
initialize full commit
Browse files Browse the repository at this point in the history
  • Loading branch information
moesmufti committed Dec 16, 2024
0 parents commit 8b328cd
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 0 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Publish Package to PyPI

on:
push:
tags:
- 'v*'

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
63 changes: 63 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
/tests

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDEs
.vscode/
.idea/

# Misc
*.log
.DS_Store
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Mustafa "Moes" Mufti

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
95 changes: 95 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# XAI SDK

A lightweight Python SDK for interacting with the xAI API, designed with minimal dependencies.

## Installation

```bash
pip install xai-grok-sdk
```

## Features

- Simple and intuitive interface for x.AI API interactions
- Support for chat completions with the latest x.AI models
- Built-in function calling capabilities
- Minimal dependencies (only requires `requests`)

## Quick Start

```python
from xai_grok_sdk import XAI

# Initialize the client
xai = XAI(
api_key="your_api_key",
model="your_chosen_model"
)

# Basic chat completion
response = xai.invoke(
messages=[
{"role": "user", "content": "Hello, how are you?"}
]
)

# Using function calling - THIS IS A WORK IN PROGRESS, DOESN'T WORK YET IN THE RELEASED VERSION
tools = [
{
"function": {
"name": "get_weather",
"description": "Get the weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
}
},
"required": ["location"]
}
}
}
]

xai = XAI(
api_key="your_api_key",
model="your_chosen_model",
tools=tools
)

response = xai.invoke(
messages=[
{"role": "user", "content": "What's the weather like in San Francisco?"}
]
)
```

## API Reference

### XAI Class

#### `__init__(api_key: str, model: str, tools: Optional[List[Dict[str, Any]]] = None)`

Initialize the XAI client.

- `api_key`: Your x.AI API key
- `model`: The model to use for chat completions
- `tools`: Optional list of tools available for the model to use

#### `invoke(messages: List[Dict[str, Any]], tool_choice: str = "auto") -> Dict[str, Any]`

Run a conversation with the model.

- `messages`: List of conversation messages
- `tool_choice`: Function calling mode ('auto', 'required', 'none', or specific function)
- Returns: Dictionary containing the model's response

## License

[License information here]

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
16 changes: 16 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[build-system]
requires = ["setuptools>=75.6.0"]
build-backend = "setuptools.build_meta"

[project]
name = "xai-grok-sdk"
version = "0.0.2"
description = "Lightweight xAI SDK with minimal dependencies"
dependencies = [
"requests>=2.32.3",
]
long_description = { file = "README.md", content-type = "text/markdown" }

[tool.setuptools]
package-dir = {"" = "src"}
packages = ["xai_grok_sdk"]
3 changes: 3 additions & 0 deletions src/xai_grok_sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from xai_grok_sdk.xai import XAI

__all__ = ["XAI"]
111 changes: 111 additions & 0 deletions src/xai_grok_sdk/xai.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""Module for handling XAI API interactions."""

import json
import requests
from typing import List, Dict, Any, Optional, Callable


class XAI:
"""Class for handling XAI API interactions."""

def __init__(
self,
api_key: str,
model: str,
tools: Optional[List[Dict[str, Any]]] = None,
):
"""
Initialize the XAI client.
Args:
api_key: API key for XAI.
model: Model to use for chat completions.
tools: List of tools available for the model to use. Each tool should have a
'function' field with 'name' and an actual implementation function.
"""
self.api_key = api_key
self.model = model
self.base_url = "https://api.x.ai/v1"
self.tools = []
self.function_map: Dict[str, Callable] = {}

if tools:
for tool in tools:
if "function" in tool and "name" in tool["function"]:
if hasattr(self, tool["function"]["name"]):
self.tools.append(tool)
self.function_map[tool["function"]["name"]] = getattr(
self, tool["function"]["name"]
)

def _make_api_call(self, payload: Dict[str, Any]) -> Dict[str, Any]:
"""Make an API call to XAI."""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
}
response = requests.post(
f"{self.base_url}/chat/completions", headers=headers, json=payload
)
response.raise_for_status()
return response.json()

def invoke(
self,
messages: List[Dict[str, Any]],
tool_choice: str = "auto",
) -> Dict[str, Any]:
"""
Run a conversation with the model.
Args:
messages: List of conversation messages
tool_choice: Function calling mode ('auto', 'required', 'none', or specific function)
Returns:
Dict containing the model's response
"""
# Prepare initial payload
payload = {
"model": self.model,
"messages": messages,
}

# Only include tools-related parameters if tools are configured
if self.tools:
payload["tools"] = self.tools
payload["tool_choice"] = tool_choice

# Make initial API call
response_data = self._make_api_call(payload)

# Check if tool was called
if (
"choices" in response_data
and response_data["choices"]
and "message" in response_data["choices"][0]
and "tool_calls" in response_data["choices"][0]["message"]
):
tool_call = response_data["choices"][0]["message"]["tool_calls"][0]
function_name = tool_call["function"]["name"]
function_args = json.loads(tool_call["function"]["arguments"])

# Execute the function if it exists in the function map
if function_name in self.function_map:
function_result = self.function_map[function_name](**function_args)

# Add function result to messages
messages.append(
{
"tool_call_id": tool_call["id"],
"role": "tool",
"name": function_name,
"content": str(function_result),
}
)

# Get final response from the model
final_payload = {"model": self.model, "messages": messages}
return self._make_api_call(final_payload)

return response_data

0 comments on commit 8b328cd

Please sign in to comment.