agentkit-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentkit_sdk-0.1.0/PKG-INFO +108 -0
- agentkit_sdk-0.1.0/README.md +80 -0
- agentkit_sdk-0.1.0/pyproject.toml +49 -0
- agentkit_sdk-0.1.0/setup.cfg +4 -0
- agentkit_sdk-0.1.0/src/agentkit/__init__.py +3 -0
- agentkit_sdk-0.1.0/src/agentkit/cli/__init__.py +0 -0
- agentkit_sdk-0.1.0/src/agentkit/cli/build.py +54 -0
- agentkit_sdk-0.1.0/src/agentkit/cli/deploy.py +50 -0
- agentkit_sdk-0.1.0/src/agentkit/cli/init.py +85 -0
- agentkit_sdk-0.1.0/src/agentkit/cli/main.py +22 -0
- agentkit_sdk-0.1.0/src/agentkit/cli/serve.py +35 -0
- agentkit_sdk-0.1.0/src/agentkit/core/__init__.py +3 -0
- agentkit_sdk-0.1.0/src/agentkit/core/context.py +75 -0
- agentkit_sdk-0.1.0/src/agentkit/core/pipeline.py +132 -0
- agentkit_sdk-0.1.0/src/agentkit/core/turn_detector.py +49 -0
- agentkit_sdk-0.1.0/src/agentkit/learning/__init__.py +2 -0
- agentkit_sdk-0.1.0/src/agentkit/learning/correction.py +109 -0
- agentkit_sdk-0.1.0/src/agentkit/learning/recommender.py +76 -0
- agentkit_sdk-0.1.0/src/agentkit/memory/__init__.py +5 -0
- agentkit_sdk-0.1.0/src/agentkit/memory/base.py +114 -0
- agentkit_sdk-0.1.0/src/agentkit/memory/extractor.py +79 -0
- agentkit_sdk-0.1.0/src/agentkit/memory/markdown.py +109 -0
- agentkit_sdk-0.1.0/src/agentkit/memory/user_model.py +1 -0
- agentkit_sdk-0.1.0/src/agentkit/memory/vector.py +96 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/llm/__init__.py +5 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/llm/base.py +36 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/llm/gemini.py +59 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/llm/openai.py +59 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/stt/__init__.py +5 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/stt/base.py +21 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/stt/deepgram.py +53 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/stt/sarvam.py +45 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/tts/__init__.py +5 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/tts/base.py +21 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/tts/elevenlabs.py +40 -0
- agentkit_sdk-0.1.0/src/agentkit/providers/tts/sarvam.py +43 -0
- agentkit_sdk-0.1.0/src/agentkit/server/__init__.py +1 -0
- agentkit_sdk-0.1.0/src/agentkit/server/app.py +189 -0
- agentkit_sdk-0.1.0/src/agentkit_sdk.egg-info/PKG-INFO +108 -0
- agentkit_sdk-0.1.0/src/agentkit_sdk.egg-info/SOURCES.txt +42 -0
- agentkit_sdk-0.1.0/src/agentkit_sdk.egg-info/dependency_links.txt +1 -0
- agentkit_sdk-0.1.0/src/agentkit_sdk.egg-info/entry_points.txt +2 -0
- agentkit_sdk-0.1.0/src/agentkit_sdk.egg-info/requires.txt +22 -0
- agentkit_sdk-0.1.0/src/agentkit_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentkit-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Developer SDK for building personalized voice AI assistants
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastapi>=0.115.0
|
|
8
|
+
Requires-Dist: uvicorn[standard]>=0.32.0
|
|
9
|
+
Requires-Dist: websockets>=14.0
|
|
10
|
+
Requires-Dist: pydantic>=2.10.0
|
|
11
|
+
Requires-Dist: pydantic-settings>=2.6.0
|
|
12
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
13
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
14
|
+
Requires-Dist: click>=8.1.0
|
|
15
|
+
Requires-Dist: httpx>=0.27.0
|
|
16
|
+
Requires-Dist: google-generativeai>=0.8.0
|
|
17
|
+
Requires-Dist: openai>=1.50.0
|
|
18
|
+
Requires-Dist: qdrant-client>=1.12.0
|
|
19
|
+
Requires-Dist: numpy>=1.26.0
|
|
20
|
+
Requires-Dist: tiktoken>=0.7.0
|
|
21
|
+
Requires-Dist: aiofiles>=24.0.0
|
|
22
|
+
Requires-Dist: tenacity>=9.0.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.8.0; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy>=1.13.0; extra == "dev"
|
|
28
|
+
|
|
29
|
+
# AgentKit
|
|
30
|
+
|
|
31
|
+
Developer SDK for building personalized voice AI assistants with mobile APK generation.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Install
|
|
37
|
+
pip install agentkit
|
|
38
|
+
|
|
39
|
+
# Initialize a new agent project
|
|
40
|
+
agentkit init my-agent
|
|
41
|
+
|
|
42
|
+
# Add API keys to .env
|
|
43
|
+
cd my-agent
|
|
44
|
+
cp .env.example .env
|
|
45
|
+
|
|
46
|
+
# Start the server
|
|
47
|
+
agentkit serve
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
Edit `agent.config.yaml`:
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
agent:
|
|
56
|
+
name: "Assistant"
|
|
57
|
+
persona: "You are a helpful personal assistant..."
|
|
58
|
+
language: hinglish
|
|
59
|
+
|
|
60
|
+
voice:
|
|
61
|
+
stt:
|
|
62
|
+
provider: sarvam # or deepgram
|
|
63
|
+
api_key: ${SARVAM_API_KEY}
|
|
64
|
+
tts:
|
|
65
|
+
provider: sarvam # or elevenlabs
|
|
66
|
+
voice: "meera"
|
|
67
|
+
api_key: ${SARVAM_API_KEY}
|
|
68
|
+
|
|
69
|
+
llm:
|
|
70
|
+
provider: gemini # or openai
|
|
71
|
+
model: gemini-2.0-flash
|
|
72
|
+
api_key: ${GEMINI_API_KEY}
|
|
73
|
+
temperature: 0.7
|
|
74
|
+
|
|
75
|
+
memory:
|
|
76
|
+
type: markdown # or vector
|
|
77
|
+
backend: local # or qdrant
|
|
78
|
+
|
|
79
|
+
learning:
|
|
80
|
+
enabled: true
|
|
81
|
+
correction_detection: true
|
|
82
|
+
implicit_feedback: true
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Commands
|
|
86
|
+
|
|
87
|
+
- `agentkit init` - Initialize a new project
|
|
88
|
+
- `agentkit serve` - Start the FastAPI server
|
|
89
|
+
- `agentkit build android` - Build Android APK
|
|
90
|
+
- `agentkit deploy --platform railway` - Deploy to Railway or Render
|
|
91
|
+
|
|
92
|
+
## Architecture
|
|
93
|
+
|
|
94
|
+
- **CLI** - Python Click commands for init, serve, build, deploy
|
|
95
|
+
- **Pipeline** - Streaming STT → LLM → TTS orchestration with <500ms latency
|
|
96
|
+
- **Memory** - Markdown (MVP) or Qdrant vector storage with semantic retrieval
|
|
97
|
+
- **Learning** - Explicit/implicit correction detection, proactive recommendations
|
|
98
|
+
- **Mobile** - React Native + Expo VoiceOrb interface
|
|
99
|
+
|
|
100
|
+
## Environment Variables
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
SARVAM_API_KEY=your_sarvam_key
|
|
104
|
+
GEMINI_API_KEY=your_gemini_key
|
|
105
|
+
DEEPGRAM_API_KEY=your_deepgram_key
|
|
106
|
+
ELEVENLABS_API_KEY=your_elevenlabs_key
|
|
107
|
+
OPENAI_API_KEY=your_openai_key
|
|
108
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# AgentKit
|
|
2
|
+
|
|
3
|
+
Developer SDK for building personalized voice AI assistants with mobile APK generation.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install
|
|
9
|
+
pip install agentkit
|
|
10
|
+
|
|
11
|
+
# Initialize a new agent project
|
|
12
|
+
agentkit init my-agent
|
|
13
|
+
|
|
14
|
+
# Add API keys to .env
|
|
15
|
+
cd my-agent
|
|
16
|
+
cp .env.example .env
|
|
17
|
+
|
|
18
|
+
# Start the server
|
|
19
|
+
agentkit serve
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Configuration
|
|
23
|
+
|
|
24
|
+
Edit `agent.config.yaml`:
|
|
25
|
+
|
|
26
|
+
```yaml
|
|
27
|
+
agent:
|
|
28
|
+
name: "Assistant"
|
|
29
|
+
persona: "You are a helpful personal assistant..."
|
|
30
|
+
language: hinglish
|
|
31
|
+
|
|
32
|
+
voice:
|
|
33
|
+
stt:
|
|
34
|
+
provider: sarvam # or deepgram
|
|
35
|
+
api_key: ${SARVAM_API_KEY}
|
|
36
|
+
tts:
|
|
37
|
+
provider: sarvam # or elevenlabs
|
|
38
|
+
voice: "meera"
|
|
39
|
+
api_key: ${SARVAM_API_KEY}
|
|
40
|
+
|
|
41
|
+
llm:
|
|
42
|
+
provider: gemini # or openai
|
|
43
|
+
model: gemini-2.0-flash
|
|
44
|
+
api_key: ${GEMINI_API_KEY}
|
|
45
|
+
temperature: 0.7
|
|
46
|
+
|
|
47
|
+
memory:
|
|
48
|
+
type: markdown # or vector
|
|
49
|
+
backend: local # or qdrant
|
|
50
|
+
|
|
51
|
+
learning:
|
|
52
|
+
enabled: true
|
|
53
|
+
correction_detection: true
|
|
54
|
+
implicit_feedback: true
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Commands
|
|
58
|
+
|
|
59
|
+
- `agentkit init` - Initialize a new project
|
|
60
|
+
- `agentkit serve` - Start the FastAPI server
|
|
61
|
+
- `agentkit build android` - Build Android APK
|
|
62
|
+
- `agentkit deploy --platform railway` - Deploy to Railway or Render
|
|
63
|
+
|
|
64
|
+
## Architecture
|
|
65
|
+
|
|
66
|
+
- **CLI** - Python Click commands for init, serve, build, deploy
|
|
67
|
+
- **Pipeline** - Streaming STT → LLM → TTS orchestration with <500ms latency
|
|
68
|
+
- **Memory** - Markdown (MVP) or Qdrant vector storage with semantic retrieval
|
|
69
|
+
- **Learning** - Explicit/implicit correction detection, proactive recommendations
|
|
70
|
+
- **Mobile** - React Native + Expo VoiceOrb interface
|
|
71
|
+
|
|
72
|
+
## Environment Variables
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
SARVAM_API_KEY=your_sarvam_key
|
|
76
|
+
GEMINI_API_KEY=your_gemini_key
|
|
77
|
+
DEEPGRAM_API_KEY=your_deepgram_key
|
|
78
|
+
ELEVENLABS_API_KEY=your_elevenlabs_key
|
|
79
|
+
OPENAI_API_KEY=your_openai_key
|
|
80
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agentkit-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Developer SDK for building personalized voice AI assistants"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"fastapi>=0.115.0",
|
|
13
|
+
"uvicorn[standard]>=0.32.0",
|
|
14
|
+
"websockets>=14.0",
|
|
15
|
+
"pydantic>=2.10.0",
|
|
16
|
+
"pydantic-settings>=2.6.0",
|
|
17
|
+
"python-dotenv>=1.0.0",
|
|
18
|
+
"pyyaml>=6.0.0",
|
|
19
|
+
"click>=8.1.0",
|
|
20
|
+
"httpx>=0.27.0",
|
|
21
|
+
"google-generativeai>=0.8.0",
|
|
22
|
+
"openai>=1.50.0",
|
|
23
|
+
"qdrant-client>=1.12.0",
|
|
24
|
+
"numpy>=1.26.0",
|
|
25
|
+
"tiktoken>=0.7.0",
|
|
26
|
+
"aiofiles>=24.0.0",
|
|
27
|
+
"tenacity>=9.0.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
dev = [
|
|
32
|
+
"pytest>=8.0.0",
|
|
33
|
+
"pytest-asyncio>=0.24.0",
|
|
34
|
+
"ruff>=0.8.0",
|
|
35
|
+
"mypy>=1.13.0",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
agentkit = "agentkit.cli.main:cli"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
where = ["src"]
|
|
43
|
+
include = ["agentkit", "agentkit.cli", "agentkit.core", "agentkit.memory", "agentkit.learning", "agentkit.providers.*", "agentkit.server"]
|
|
44
|
+
|
|
45
|
+
[tool.ruff]
|
|
46
|
+
target-version = "py311"
|
|
47
|
+
|
|
48
|
+
[tool.mypy]
|
|
49
|
+
python-version = "3.11"
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command()
|
|
11
|
+
@click.option("--config", default="agent.config.yaml", help="Config file path")
|
|
12
|
+
@click.option("--output", default="build/", help="Output directory")
|
|
13
|
+
def android(config: str, output: str):
|
|
14
|
+
"""Build Android APK from AgentShell template."""
|
|
15
|
+
|
|
16
|
+
if not Path(config).exists():
|
|
17
|
+
click.echo(f"Error: Config file '{config}' not found.")
|
|
18
|
+
sys.exit(1)
|
|
19
|
+
|
|
20
|
+
click.echo("Building Android APK...")
|
|
21
|
+
|
|
22
|
+
import yaml
|
|
23
|
+
with open(config) as f:
|
|
24
|
+
cfg = yaml.safe_load(f)
|
|
25
|
+
|
|
26
|
+
agent_name = cfg.get("agent", {}).get("name", "Agent")
|
|
27
|
+
backend_url = cfg.get("deployment", {}).get("backend_url", "ws://localhost:8000/ws/voice")
|
|
28
|
+
|
|
29
|
+
template_dir = Path(__file__).parent.parent / "mobile" / "AgentShell"
|
|
30
|
+
|
|
31
|
+
if not template_dir.exists():
|
|
32
|
+
click.echo("Error: AgentShell template not found.")
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
project_dir = Path(output)
|
|
36
|
+
project_dir.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
|
|
38
|
+
shutil.copytree(template_dir, project_dir / "AgentShell", dirs_exist_ok=True)
|
|
39
|
+
|
|
40
|
+
app_js = project_dir / "AgentShell" / "App.jsx"
|
|
41
|
+
if app_js.exists():
|
|
42
|
+
content = app_js.read_text()
|
|
43
|
+
content = content.replace("ws://localhost:8000/ws/voice", backend_url)
|
|
44
|
+
content = content.replace("Assistant", agent_name)
|
|
45
|
+
app_js.write_text(content)
|
|
46
|
+
|
|
47
|
+
click.echo("Installing dependencies...")
|
|
48
|
+
os.chdir(project_dir / "AgentShell")
|
|
49
|
+
subprocess.run(["npm", "install"], check=True)
|
|
50
|
+
|
|
51
|
+
click.echo("Building Android APK...")
|
|
52
|
+
subprocess.run(["npx", "expo", "run:android"], check=True)
|
|
53
|
+
|
|
54
|
+
click.echo(f"APK built at: {project_dir / "AgentShell/android/app/build/outputs/apk/release/"}")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
PLATFORMS = ["railway", "render"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command()
|
|
11
|
+
@click.option("--platform", type=click.Choice(PLATFORMS), required=True, help="Deployment platform")
|
|
12
|
+
@click.option("--config", default="agent.config.yaml", help="Config file path")
|
|
13
|
+
def deploy(platform: str, config: str):
|
|
14
|
+
"""Deploy backend to Railway or Render."""
|
|
15
|
+
|
|
16
|
+
click.echo(f"Deploying to {platform}...")
|
|
17
|
+
|
|
18
|
+
if platform == "railway":
|
|
19
|
+
_deploy_railway()
|
|
20
|
+
elif platform == "render":
|
|
21
|
+
_deploy_render()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _deploy_railway():
|
|
25
|
+
try:
|
|
26
|
+
result = subprocess.run(["railway", "login"], capture_output=True)
|
|
27
|
+
if result.returncode != 0:
|
|
28
|
+
click.echo("Please install Railway CLI: npm install -g @railway/cli")
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
|
|
31
|
+
subprocess.run(["railway", "init"], check=True)
|
|
32
|
+
subprocess.run(["railway", "up"], check=True)
|
|
33
|
+
|
|
34
|
+
click.echo("Deployed to Railway! Run 'railway link' to connect.")
|
|
35
|
+
except FileNotFoundError:
|
|
36
|
+
click.echo("Railway CLI not found. Install with: npm install -g @railway/cli")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _deploy_render():
|
|
40
|
+
try:
|
|
41
|
+
result = subprocess.run(["render", "--version"], capture_output=True)
|
|
42
|
+
if result.returncode != 0:
|
|
43
|
+
click.echo("Please install Render CLI: npm install -g render-cli")
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
|
|
46
|
+
subprocess.run(["render", "blueprint", "init"], check=True)
|
|
47
|
+
|
|
48
|
+
click.echo("Deployed to Render! Check your dashboard for the live URL.")
|
|
49
|
+
except FileNotFoundError:
|
|
50
|
+
click.echo("Render CLI not found. Install with: npm install -g render-cli")
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
import yaml
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
@click.option("--name", default="my-agent", help="Agent name")
|
|
11
|
+
@click.option("--output-dir", default=".", help="Output directory")
|
|
12
|
+
def init(name: str, output_dir: str):
|
|
13
|
+
"""Initialize a new AgentKit project."""
|
|
14
|
+
|
|
15
|
+
project_dir = Path(output_dir) / name
|
|
16
|
+
project_dir.mkdir(parents=True, exist_ok=True)
|
|
17
|
+
|
|
18
|
+
config_content = {
|
|
19
|
+
"agent": {
|
|
20
|
+
"name": name,
|
|
21
|
+
"persona": "You are a helpful personal assistant that remembers conversations and learns from corrections.",
|
|
22
|
+
"language": "hinglish"
|
|
23
|
+
},
|
|
24
|
+
"voice": {
|
|
25
|
+
"enabled": True,
|
|
26
|
+
"stt": {
|
|
27
|
+
"provider": "sarvam",
|
|
28
|
+
"api_key": "${SARVAM_API_KEY}"
|
|
29
|
+
},
|
|
30
|
+
"tts": {
|
|
31
|
+
"provider": "sarvam",
|
|
32
|
+
"voice": "meera",
|
|
33
|
+
"api_key": "${SARVAM_API_KEY}"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"llm": {
|
|
37
|
+
"provider": "gemini",
|
|
38
|
+
"model": "gemini-2.0-flash",
|
|
39
|
+
"api_key": "${GEMINI_API_KEY}",
|
|
40
|
+
"temperature": 0.7
|
|
41
|
+
},
|
|
42
|
+
"memory": {
|
|
43
|
+
"type": "markdown",
|
|
44
|
+
"backend": "local",
|
|
45
|
+
"episodic_window": 20,
|
|
46
|
+
"semantic_top_k": 5
|
|
47
|
+
},
|
|
48
|
+
"learning": {
|
|
49
|
+
"enabled": True,
|
|
50
|
+
"correction_detection": True,
|
|
51
|
+
"implicit_feedback": True,
|
|
52
|
+
"profile_extraction": True
|
|
53
|
+
},
|
|
54
|
+
"deployment": {
|
|
55
|
+
"type": "self-host",
|
|
56
|
+
"port": 8000
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
config_path = project_dir / "agent.config.yaml"
|
|
61
|
+
with open(config_path, "w") as f:
|
|
62
|
+
yaml.dump(config_content, f, default_flow_style=False)
|
|
63
|
+
|
|
64
|
+
env_example = """# API Keys
|
|
65
|
+
SARVAM_API_KEY=your_sarvam_key
|
|
66
|
+
GEMINI_API_KEY=your_gemini_key
|
|
67
|
+
DEEPGRAM_API_KEY=your_deepgram_key
|
|
68
|
+
ELEVENLABS_API_KEY=your_elevenlabs_key
|
|
69
|
+
OPENAI_API_KEY=your_openai_key
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
env_path = project_dir / ".env.example"
|
|
73
|
+
with open(env_path, "w") as f:
|
|
74
|
+
f.write(env_example)
|
|
75
|
+
|
|
76
|
+
src_dir = project_dir / "src"
|
|
77
|
+
src_dir.mkdir(exist_ok=True)
|
|
78
|
+
|
|
79
|
+
(src_dir / "__init__.py").touch()
|
|
80
|
+
|
|
81
|
+
click.echo(f"AgentKit project '{name}' created at {project_dir}")
|
|
82
|
+
click.echo(f"Next steps:")
|
|
83
|
+
click.echo(f" 1. cd {project_dir}")
|
|
84
|
+
click.echo(f" 2. cp .env.example .env and add your API keys")
|
|
85
|
+
click.echo(f" 3. agentkit serve")
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from agentkit.cli.init import init
|
|
4
|
+
from agentkit.cli.serve import serve
|
|
5
|
+
from agentkit.cli.build import android
|
|
6
|
+
from agentkit.cli.deploy import deploy
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group()
|
|
10
|
+
def cli():
|
|
11
|
+
"""AgentKit - Build personalized voice AI assistants"""
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
cli.add_command(init)
|
|
16
|
+
cli.add_command(serve)
|
|
17
|
+
cli.add_command(android)
|
|
18
|
+
cli.add_command(deploy)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
cli()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from dotenv import load_dotenv
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
@click.option("--config", default="agent.config.yaml", help="Config file path")
|
|
11
|
+
@click.option("--port", default=8000, help="Server port")
|
|
12
|
+
@click.option("--reload", is_flag=True, help="Enable auto-reload")
|
|
13
|
+
def serve(config: str, port: int, reload: bool):
|
|
14
|
+
"""Start the AgentKit server."""
|
|
15
|
+
|
|
16
|
+
if not Path(config).exists():
|
|
17
|
+
click.echo(f"Error: Config file '{config}' not found.")
|
|
18
|
+
click.echo("Run 'agentkit init' first to create a project.")
|
|
19
|
+
sys.exit(1)
|
|
20
|
+
|
|
21
|
+
load_dotenv()
|
|
22
|
+
|
|
23
|
+
import uvicorn
|
|
24
|
+
from agentkit.server.app import app
|
|
25
|
+
|
|
26
|
+
click.echo(f"Starting AgentKit server on port {port}...")
|
|
27
|
+
click.echo(f"Playground available at http://localhost:{port}/playground")
|
|
28
|
+
|
|
29
|
+
uvicorn.run(
|
|
30
|
+
"agentkit.server.app:app",
|
|
31
|
+
host="0.0.0.0",
|
|
32
|
+
port=port,
|
|
33
|
+
reload=reload,
|
|
34
|
+
env_file=".env",
|
|
35
|
+
)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclass
|
|
5
|
+
class MemoryContext:
|
|
6
|
+
user_profile_summary: str = ""
|
|
7
|
+
semantic_episodes: str = ""
|
|
8
|
+
correction_rules: str = ""
|
|
9
|
+
recent_turns: str = ""
|
|
10
|
+
|
|
11
|
+
def assemble(self) -> str:
|
|
12
|
+
parts = []
|
|
13
|
+
if self.user_profile_summary:
|
|
14
|
+
parts.append(f"User Profile:\n{self.user_profile_summary}")
|
|
15
|
+
if self.semantic_episodes:
|
|
16
|
+
parts.append(f"Relevant History:\n{self.semantic_episodes}")
|
|
17
|
+
if self.correction_rules:
|
|
18
|
+
parts.append(f"Correction Rules:\n{self.correction_rules}")
|
|
19
|
+
if self.recent_turns:
|
|
20
|
+
parts.append(f"Recent Conversation:\n{self.recent_turns}")
|
|
21
|
+
return "\n\n".join(parts)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ContextAssembler:
|
|
25
|
+
def __init__(self, memory):
|
|
26
|
+
self.memory = memory
|
|
27
|
+
|
|
28
|
+
async def assemble(self, query: str, user_id: str) -> MemoryContext:
|
|
29
|
+
context = MemoryContext()
|
|
30
|
+
|
|
31
|
+
user_model = await self.memory.get_user_model(user_id)
|
|
32
|
+
if user_model:
|
|
33
|
+
context.user_profile_summary = self._summarize_user_model(user_model)
|
|
34
|
+
|
|
35
|
+
semantic_results = await self.memory.retrieve(query, user_id)
|
|
36
|
+
if semantic_results:
|
|
37
|
+
context.semantic_episodes = self._format_semantic_results(semantic_results)
|
|
38
|
+
|
|
39
|
+
if user_model and user_model.correction_rules:
|
|
40
|
+
context.correction_rules = self._format_corrections(user_model.correction_rules)
|
|
41
|
+
|
|
42
|
+
recent_turns = await self.memory.get_recent_turns(user_id, limit=20)
|
|
43
|
+
if recent_turns:
|
|
44
|
+
context.recent_turns = self._format_recent_turns(recent_turns)
|
|
45
|
+
|
|
46
|
+
return context
|
|
47
|
+
|
|
48
|
+
def _summarize_user_model(self, user_model) -> str:
|
|
49
|
+
parts = [f"Name: {user_model.name}"]
|
|
50
|
+
if user_model.communication_style:
|
|
51
|
+
parts.append(f"Style: {user_model.communication_style}")
|
|
52
|
+
if user_model.inferred_interests:
|
|
53
|
+
parts.append(f"Interests: {', '.join(user_model.inferred_interests[:5])}")
|
|
54
|
+
if user_model.stated_goals:
|
|
55
|
+
parts.append(f"Goals: {', '.join(user_model.stated_goals[:3])}")
|
|
56
|
+
return "\n".join(parts)
|
|
57
|
+
|
|
58
|
+
def _format_semantic_results(self, results: list) -> str:
|
|
59
|
+
formatted = []
|
|
60
|
+
for r in results[:5]:
|
|
61
|
+
formatted.append(f"- {r.get('content', '')[:200]}")
|
|
62
|
+
return "\n".join(formatted)
|
|
63
|
+
|
|
64
|
+
def _format_corrections(self, corrections: list) -> str:
|
|
65
|
+
formatted = []
|
|
66
|
+
for c in corrections[:10]:
|
|
67
|
+
formatted.append(f"- {c.get('rule', '')}")
|
|
68
|
+
return "\n".join(formatted)
|
|
69
|
+
|
|
70
|
+
def _format_recent_turns(self, turns: list) -> str:
|
|
71
|
+
formatted = []
|
|
72
|
+
for turn in turns:
|
|
73
|
+
formatted.append(f"User: {turn.get('user_message', '')}")
|
|
74
|
+
formatted.append(f"Assistant: {turn.get('assistant_message', '')}")
|
|
75
|
+
return "\n".join(formatted[-40:])
|