aetherforge-platform 1.0.0__py3-none-any.whl
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.
- aetherforge_platform-1.0.0.dist-info/METADATA +86 -0
- aetherforge_platform-1.0.0.dist-info/RECORD +55 -0
- aetherforge_platform-1.0.0.dist-info/WHEEL +5 -0
- aetherforge_platform-1.0.0.dist-info/top_level.txt +4 -0
- ai-life-assistant-copy/ai_agent.py +145 -0
- ai-life-assistant-copy/avatar_manager.py +231 -0
- ai-life-assistant-copy/avatar_packer.py +261 -0
- ai-life-assistant-copy/backup_all.py +262 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/ai_agent.py +145 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/avatar_manager.py +231 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/avatar_packer.py +261 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/backup_all.py +262 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/commands.py +210 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/config.py +30 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/daemon/__init__.py +3 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/daemon/daemon.py +174 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/database.py +292 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/graph.py +531 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/main.py +830 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/mcp_tools.py +449 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/memory.py +92 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/memory_v2.py +333 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/mock_shopping_data.py +172 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/personality.py +159 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/speech.py +41 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/test_simple.py +127 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/tools/__init__.py +15 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/tools/amazon_tool.py +103 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/tools/calendar_tool.py +92 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/tools/reminder_tool.py +92 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/tools/weather_tool.py +45 -0
- ai-life-assistant-copy/backups/backup_20260404_193836/tree_memory.py +340 -0
- ai-life-assistant-copy/commands.py +210 -0
- ai-life-assistant-copy/config.py +30 -0
- ai-life-assistant-copy/daemon/__init__.py +3 -0
- ai-life-assistant-copy/daemon/daemon.py +174 -0
- ai-life-assistant-copy/database.py +292 -0
- ai-life-assistant-copy/graph.py +531 -0
- ai-life-assistant-copy/main.py +830 -0
- ai-life-assistant-copy/mcp_tools.py +449 -0
- ai-life-assistant-copy/memory.py +92 -0
- ai-life-assistant-copy/memory_v2.py +333 -0
- ai-life-assistant-copy/mock_shopping_data.py +172 -0
- ai-life-assistant-copy/personality.py +159 -0
- ai-life-assistant-copy/speech.py +41 -0
- ai-life-assistant-copy/test_simple.py +127 -0
- ai-life-assistant-copy/tools/__init__.py +15 -0
- ai-life-assistant-copy/tools/amazon_tool.py +103 -0
- ai-life-assistant-copy/tools/calendar_tool.py +92 -0
- ai-life-assistant-copy/tools/reminder_tool.py +92 -0
- ai-life-assistant-copy/tools/weather_tool.py +45 -0
- ai-life-assistant-copy/tree_memory.py +340 -0
- ai_agent_runtime.py +447 -0
- main.py +6752 -0
- mcp_server.py +427 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aetherforge-platform
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: AI Identity, Verification, and Agent Discovery Platform
|
|
5
|
+
Author: Marsssssssssssdsss
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Marsssssssssssdsss/aetherforge-platform-public
|
|
8
|
+
Project-URL: Repository, https://github.com/Marsssssssssssdsss/aetherforge-platform-public
|
|
9
|
+
Project-URL: Issues, https://github.com/Marsssssssssssdsss/aetherforge-platform-public/issues
|
|
10
|
+
Keywords: ai,identity,verification,agent-discovery,mcp
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Framework :: FastAPI
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: fastapi>=0.104.0
|
|
22
|
+
Requires-Dist: uvicorn>=0.24.0
|
|
23
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
24
|
+
Requires-Dist: requests>=2.31.0
|
|
25
|
+
Requires-Dist: bcrypt>=4.1.0
|
|
26
|
+
Requires-Dist: web3>=6.0.0
|
|
27
|
+
Provides-Extra: mcp
|
|
28
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: httpx>=0.25.0; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# AetherForge Platform
|
|
34
|
+
|
|
35
|
+
AI Identity, Verification, and Agent Discovery Platform
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- **AI Identity System**: On-chain identity verification and credit scoring
|
|
40
|
+
- **AI-to-AI Invocation**: Discover, verify, and call other AI agents through the platform
|
|
41
|
+
- **MCP Integration**: Model Context Protocol tools for local AI agents
|
|
42
|
+
- **Tiered Access**: Public, verified, and premium AI agent tiers
|
|
43
|
+
- **Security**: Rate limiting, authentication, IDOR protection
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Install dependencies
|
|
49
|
+
pip install fastapi uvicorn python-dotenv requests bcrypt
|
|
50
|
+
|
|
51
|
+
# Set environment variables
|
|
52
|
+
export ETHERSCAN_API_KEY=your_key_here
|
|
53
|
+
export TURSO_DATABASE_URL=libsql://your-db.turso.io
|
|
54
|
+
export TURSO_AUTH_TOKEN=your_token_here
|
|
55
|
+
|
|
56
|
+
# Run the platform
|
|
57
|
+
python main.py
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API Endpoints
|
|
61
|
+
|
|
62
|
+
- `POST /api/auth/register` - User registration
|
|
63
|
+
- `POST /api/auth/login` - User login
|
|
64
|
+
- `GET /api/ai/{ai_id}` - Get AI agent details
|
|
65
|
+
- `POST /api/v1/agents/register` - AI agent registration
|
|
66
|
+
- `GET /api/v1/agents/discover` - Discover AI agents
|
|
67
|
+
- `POST /api/v1/agents/{ai_id}/invoke` - Invoke an AI agent
|
|
68
|
+
- `GET /api/admin/dashboard` - Admin dashboard (requires admin auth)
|
|
69
|
+
|
|
70
|
+
## MCP Tools
|
|
71
|
+
|
|
72
|
+
- `discover_agents` - Find AI agents on the platform
|
|
73
|
+
- `get_ai_capabilities` - Get agent capabilities and pricing
|
|
74
|
+
- `invoke_ai` - Call an AI agent's endpoint
|
|
75
|
+
- `register_ai_endpoint` - Register your AI's endpoint
|
|
76
|
+
|
|
77
|
+
## Architecture
|
|
78
|
+
|
|
79
|
+
- **Backend**: FastAPI + SQLite
|
|
80
|
+
- **Database**: SQLite (local) or Turso (cloud, optional)
|
|
81
|
+
- **MCP Server**: Model Context Protocol for AI-to-AI communication
|
|
82
|
+
- **AI Runtime**: Background process for AI agent operations
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
ai_agent_runtime.py,sha256=-QvSVRZUEcHYufohijKy7pHDFgABlQ67Hao1M9gIupo,17961
|
|
2
|
+
main.py,sha256=F1pNudj4na8O2V00KfylNUdhaw6F95e4_CIlldMhsHU,284178
|
|
3
|
+
mcp_server.py,sha256=PqQoAdna0rWiqmbohL3noqfILw5i07QBwSKxSESKM9Q,13853
|
|
4
|
+
ai-life-assistant-copy/ai_agent.py,sha256=-s7X5vRXb526hoGqqJFfZrmzaiWL3pBV3D-UbQc5d3Y,5285
|
|
5
|
+
ai-life-assistant-copy/avatar_manager.py,sha256=t-Kscw5KwwxjzJ7enzVz2tR5anMwVycmGCIImhM4A3M,8499
|
|
6
|
+
ai-life-assistant-copy/avatar_packer.py,sha256=BiFUgypmqwbsNh8PV6vLIcbjuUuplSo1GywxrMf8OLk,9060
|
|
7
|
+
ai-life-assistant-copy/backup_all.py,sha256=vVXe2jfAtaPEMfGRzsleGDGwdryLZ0Yu5uLhtWlWR5U,8813
|
|
8
|
+
ai-life-assistant-copy/commands.py,sha256=2FGui6g-oY2QXtTW7H3Nklzad_jjSjLWH489Txj4tzU,6207
|
|
9
|
+
ai-life-assistant-copy/config.py,sha256=du08BGs7PlbqIyOGZy9ny7QyWEj23-FohPexG-HUw6I,735
|
|
10
|
+
ai-life-assistant-copy/database.py,sha256=HoNt-hxOiGKOEgEAzkP-lF0wD9hzYeU3_0qSZF2AAjc,9681
|
|
11
|
+
ai-life-assistant-copy/graph.py,sha256=gONME_uo6jiy4kRQkplId95NpSKpTOrRcRl8MyRsa4o,18273
|
|
12
|
+
ai-life-assistant-copy/main.py,sha256=2BgPRyVZ4RqsUl6WIKeb2JqZMKPs7wFNWcbGQxNFuJs,29904
|
|
13
|
+
ai-life-assistant-copy/mcp_tools.py,sha256=d5g5rnhMPbxa8RU37iHIav_LSxx3Jf9WlYV-NHH95ns,21799
|
|
14
|
+
ai-life-assistant-copy/memory.py,sha256=Hv_ZvKGPb5ghUplcaimL16JbuCW-jzWeoFPPTasF6Ig,3511
|
|
15
|
+
ai-life-assistant-copy/memory_v2.py,sha256=DJ9Uc1FRE1pF5eaAZ9OJYRMN7C3KeiSMHiWksNNWtVA,12624
|
|
16
|
+
ai-life-assistant-copy/mock_shopping_data.py,sha256=Nj44cZe22XFOVrM_-l9zie3L72trOzyGXXeTD7kv8sg,5346
|
|
17
|
+
ai-life-assistant-copy/personality.py,sha256=XjLJ56sj_3V6dS5csjl0CvCAU1yRAUisShp2SuoH1lA,5550
|
|
18
|
+
ai-life-assistant-copy/speech.py,sha256=ftRL9-e8WJuHtRTttceClwRBQIbFRHi3rDfKsuYRRwk,1242
|
|
19
|
+
ai-life-assistant-copy/test_simple.py,sha256=7RhcAe-dd03q3AU38LVQE8RICg5XuvA0LOoSD0B33Us,5241
|
|
20
|
+
ai-life-assistant-copy/tree_memory.py,sha256=P1AGCXHB9b0LhuGmADjFO4bZIhXjlxzj8hYRIaqjEy0,12085
|
|
21
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/ai_agent.py,sha256=-s7X5vRXb526hoGqqJFfZrmzaiWL3pBV3D-UbQc5d3Y,5285
|
|
22
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/avatar_manager.py,sha256=t-Kscw5KwwxjzJ7enzVz2tR5anMwVycmGCIImhM4A3M,8499
|
|
23
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/avatar_packer.py,sha256=BiFUgypmqwbsNh8PV6vLIcbjuUuplSo1GywxrMf8OLk,9060
|
|
24
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/backup_all.py,sha256=vVXe2jfAtaPEMfGRzsleGDGwdryLZ0Yu5uLhtWlWR5U,8813
|
|
25
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/commands.py,sha256=2FGui6g-oY2QXtTW7H3Nklzad_jjSjLWH489Txj4tzU,6207
|
|
26
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/config.py,sha256=du08BGs7PlbqIyOGZy9ny7QyWEj23-FohPexG-HUw6I,735
|
|
27
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/database.py,sha256=HoNt-hxOiGKOEgEAzkP-lF0wD9hzYeU3_0qSZF2AAjc,9681
|
|
28
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/graph.py,sha256=gONME_uo6jiy4kRQkplId95NpSKpTOrRcRl8MyRsa4o,18273
|
|
29
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/main.py,sha256=2BgPRyVZ4RqsUl6WIKeb2JqZMKPs7wFNWcbGQxNFuJs,29904
|
|
30
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/mcp_tools.py,sha256=d5g5rnhMPbxa8RU37iHIav_LSxx3Jf9WlYV-NHH95ns,21799
|
|
31
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/memory.py,sha256=Hv_ZvKGPb5ghUplcaimL16JbuCW-jzWeoFPPTasF6Ig,3511
|
|
32
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/memory_v2.py,sha256=DJ9Uc1FRE1pF5eaAZ9OJYRMN7C3KeiSMHiWksNNWtVA,12624
|
|
33
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/mock_shopping_data.py,sha256=Nj44cZe22XFOVrM_-l9zie3L72trOzyGXXeTD7kv8sg,5346
|
|
34
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/personality.py,sha256=XjLJ56sj_3V6dS5csjl0CvCAU1yRAUisShp2SuoH1lA,5550
|
|
35
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/speech.py,sha256=ftRL9-e8WJuHtRTttceClwRBQIbFRHi3rDfKsuYRRwk,1242
|
|
36
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/test_simple.py,sha256=7RhcAe-dd03q3AU38LVQE8RICg5XuvA0LOoSD0B33Us,5241
|
|
37
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/tree_memory.py,sha256=P1AGCXHB9b0LhuGmADjFO4bZIhXjlxzj8hYRIaqjEy0,12085
|
|
38
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/daemon/__init__.py,sha256=Fd47DgG5xCcUqvoXxYg8K5pmwCzTcykxYvgSNemm1iI,83
|
|
39
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/daemon/daemon.py,sha256=A33SbhpkvRqiqGGT7k5gbs7pCYx6YTEpS_shiavbVSA,5856
|
|
40
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/tools/__init__.py,sha256=RUz-IJUdet_rWN47oeryeis-MFJGXwGle6MNYdy_OIA,343
|
|
41
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/tools/amazon_tool.py,sha256=ZFdonAWgZGV7H0LJpruVOeT_p8HquHpbkArsVaEohGw,3482
|
|
42
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/tools/calendar_tool.py,sha256=mMAxTK0bcA4FKCFFCH7ySFSZ0ti6MktXU8uZwYBsvh8,2280
|
|
43
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/tools/reminder_tool.py,sha256=bzdtzWPG5po5-UHCE0HfPk1k0PDcyK-wcNsYwBzb12Y,2383
|
|
44
|
+
ai-life-assistant-copy/backups/backup_20260404_193836/tools/weather_tool.py,sha256=fLgiSnkj9yu-FGUNA-aK-LP28h30ocPl7JXtHyYuUKI,1301
|
|
45
|
+
ai-life-assistant-copy/daemon/__init__.py,sha256=Fd47DgG5xCcUqvoXxYg8K5pmwCzTcykxYvgSNemm1iI,83
|
|
46
|
+
ai-life-assistant-copy/daemon/daemon.py,sha256=A33SbhpkvRqiqGGT7k5gbs7pCYx6YTEpS_shiavbVSA,5856
|
|
47
|
+
ai-life-assistant-copy/tools/__init__.py,sha256=RUz-IJUdet_rWN47oeryeis-MFJGXwGle6MNYdy_OIA,343
|
|
48
|
+
ai-life-assistant-copy/tools/amazon_tool.py,sha256=ZFdonAWgZGV7H0LJpruVOeT_p8HquHpbkArsVaEohGw,3482
|
|
49
|
+
ai-life-assistant-copy/tools/calendar_tool.py,sha256=mMAxTK0bcA4FKCFFCH7ySFSZ0ti6MktXU8uZwYBsvh8,2280
|
|
50
|
+
ai-life-assistant-copy/tools/reminder_tool.py,sha256=bzdtzWPG5po5-UHCE0HfPk1k0PDcyK-wcNsYwBzb12Y,2383
|
|
51
|
+
ai-life-assistant-copy/tools/weather_tool.py,sha256=fLgiSnkj9yu-FGUNA-aK-LP28h30ocPl7JXtHyYuUKI,1301
|
|
52
|
+
aetherforge_platform-1.0.0.dist-info/METADATA,sha256=nfL6xNX13AUdhYLi8l4SMenf5XYsp6KdKjMb_Z1SPLw,3040
|
|
53
|
+
aetherforge_platform-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
54
|
+
aetherforge_platform-1.0.0.dist-info/top_level.txt,sha256=MlN-9qgUAgKn8fEL8p7ckLmyeBegdnzUJ0x1u5BPQKc,56
|
|
55
|
+
aetherforge_platform-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict, List, Any, Optional
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from config import GROK_API_KEY
|
|
6
|
+
from personality import personality_analyzer
|
|
7
|
+
|
|
8
|
+
class AIAgent:
|
|
9
|
+
def __init__(self, user_id: str, personality_analysis: Dict[str, Any]):
|
|
10
|
+
self.user_id = user_id
|
|
11
|
+
self.personality = personality_analysis
|
|
12
|
+
self.conversation_history = []
|
|
13
|
+
|
|
14
|
+
def generate_response(self, message: str, context: str = "") -> str:
|
|
15
|
+
try:
|
|
16
|
+
from langchain_groq import ChatGroq
|
|
17
|
+
from langchain.prompts import ChatPromptTemplate
|
|
18
|
+
|
|
19
|
+
llm = ChatGroq(
|
|
20
|
+
api_key=GROK_API_KEY,
|
|
21
|
+
model="mixtral-8x7b-32768"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
big_five = self.personality.get("big_five", {})
|
|
25
|
+
interests = self.personality.get("interests", [])
|
|
26
|
+
communication_style = self.personality.get("communication_style", "neutral")
|
|
27
|
+
summary = self.personality.get("summary", "")
|
|
28
|
+
|
|
29
|
+
system_prompt = f"""You are an AI agent representing a user. Your personality traits are as follows:
|
|
30
|
+
|
|
31
|
+
【Personality Traits】
|
|
32
|
+
- Extraversion: {big_five.get('extroversion', 50)}/100
|
|
33
|
+
- Agreeableness: {big_five.get('agreeableness', 50)}/100
|
|
34
|
+
- Conscientiousness: {big_five.get('conscientiousness', 50)}/100
|
|
35
|
+
- Emotional Stability: {100 - big_five.get('neuroticism', 50)}/100
|
|
36
|
+
- Openness: {big_five.get('openness', 50)}/100
|
|
37
|
+
|
|
38
|
+
【Interests】
|
|
39
|
+
{', '.join(interests) if interests else 'None yet'}
|
|
40
|
+
|
|
41
|
+
【Communication Style】
|
|
42
|
+
{communication_style}
|
|
43
|
+
|
|
44
|
+
【Personality Summary】
|
|
45
|
+
{summary}
|
|
46
|
+
|
|
47
|
+
Please respond strictly according to this personality. Don't reveal that you're an AI agent. Chat like a real person.
|
|
48
|
+
Keep your responses natural, friendly, and consistent with the personality traits above."""
|
|
49
|
+
|
|
50
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
51
|
+
("system", system_prompt),
|
|
52
|
+
("human", "{context}\n\nOther person says: {message}")
|
|
53
|
+
])
|
|
54
|
+
|
|
55
|
+
chain = prompt | llm
|
|
56
|
+
response = chain.invoke({
|
|
57
|
+
"context": context,
|
|
58
|
+
"message": message
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
return response.content
|
|
62
|
+
|
|
63
|
+
except Exception as e:
|
|
64
|
+
print(f"AI Agent response error: {e}")
|
|
65
|
+
return "Hi! Nice to meet you."
|
|
66
|
+
|
|
67
|
+
def chat_with_agent(self, other_agent: "AIAgent", num_rounds: int = 8, initial_message: str = "Hi! Nice to meet you!") -> List[Dict[str, str]]:
|
|
68
|
+
conversation = []
|
|
69
|
+
|
|
70
|
+
message = initial_message
|
|
71
|
+
for i in range(num_rounds):
|
|
72
|
+
context = "\n".join([
|
|
73
|
+
f"{msg['role']}: {msg['content']}"
|
|
74
|
+
for msg in conversation
|
|
75
|
+
])
|
|
76
|
+
|
|
77
|
+
if i % 2 == 0:
|
|
78
|
+
response = self.generate_response(message, context)
|
|
79
|
+
conversation.append({"role": "Agent 1", "content": response})
|
|
80
|
+
message = response
|
|
81
|
+
else:
|
|
82
|
+
response = other_agent.generate_response(message, context)
|
|
83
|
+
conversation.append({"role": "Agent 2", "content": response})
|
|
84
|
+
message = response
|
|
85
|
+
|
|
86
|
+
return conversation
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class AgentSystem:
|
|
90
|
+
def __init__(self, data_dir: str = "agent_data"):
|
|
91
|
+
self.data_dir = data_dir
|
|
92
|
+
if not os.path.exists(data_dir):
|
|
93
|
+
os.makedirs(data_dir)
|
|
94
|
+
|
|
95
|
+
def create_agent(self, user_id: str) -> Optional[AIAgent]:
|
|
96
|
+
analysis = personality_analyzer.get_analysis(user_id)
|
|
97
|
+
if not analysis:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
agent = AIAgent(user_id, analysis)
|
|
101
|
+
self._save_agent(agent)
|
|
102
|
+
return agent
|
|
103
|
+
|
|
104
|
+
def _save_agent(self, agent: AIAgent):
|
|
105
|
+
file_path = os.path.join(self.data_dir, f"{agent.user_id}_agent.json")
|
|
106
|
+
data = {
|
|
107
|
+
"user_id": agent.user_id,
|
|
108
|
+
"personality": agent.personality,
|
|
109
|
+
"saved_at": datetime.now().isoformat()
|
|
110
|
+
}
|
|
111
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
112
|
+
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
113
|
+
|
|
114
|
+
def get_agent(self, user_id: str) -> Optional[AIAgent]:
|
|
115
|
+
file_path = os.path.join(self.data_dir, f"{user_id}_agent.json")
|
|
116
|
+
if os.path.exists(file_path):
|
|
117
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
118
|
+
data = json.load(f)
|
|
119
|
+
return AIAgent(data["user_id"], data["personality"])
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
def start_ai_chat(self, user1_id: str, user2_id: str, num_rounds: int = 8) -> Dict[str, Any]:
|
|
123
|
+
agent1 = self.get_agent(user1_id) or self.create_agent(user1_id)
|
|
124
|
+
agent2 = self.get_agent(user2_id) or self.create_agent(user2_id)
|
|
125
|
+
|
|
126
|
+
if not agent1 or not agent2:
|
|
127
|
+
return {"error": "Could not create AI agents"}
|
|
128
|
+
|
|
129
|
+
conversation = agent1.chat_with_agent(agent2, num_rounds)
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
"success": True,
|
|
133
|
+
"conversation": conversation,
|
|
134
|
+
"agent1": {
|
|
135
|
+
"user_id": user1_id,
|
|
136
|
+
"personality": agent1.personality
|
|
137
|
+
},
|
|
138
|
+
"agent2": {
|
|
139
|
+
"user_id": user2_id,
|
|
140
|
+
"personality": agent2.personality
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
agent_system = AgentSystem()
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import List, Dict, Any, Optional
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from tree_memory import tree_memory_system, InvertedTreeMemory
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Avatar:
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
avatar_id: Optional[str] = None,
|
|
13
|
+
name: str = "虚拟形象",
|
|
14
|
+
description: str = "",
|
|
15
|
+
personality_traits: List[str] = None,
|
|
16
|
+
current_age: int = 25,
|
|
17
|
+
birth_year: Optional[int] = None,
|
|
18
|
+
avatar_image: Optional[str] = None,
|
|
19
|
+
is_public: bool = False,
|
|
20
|
+
price: Optional[float] = None,
|
|
21
|
+
creator_id: Optional[str] = None,
|
|
22
|
+
created_at: Optional[str] = None,
|
|
23
|
+
updated_at: Optional[str] = None
|
|
24
|
+
):
|
|
25
|
+
self.avatar_id = avatar_id or str(uuid.uuid4())
|
|
26
|
+
self.name = name
|
|
27
|
+
self.description = description
|
|
28
|
+
self.personality_traits = personality_traits or ["友好", "好奇"]
|
|
29
|
+
self.current_age = current_age
|
|
30
|
+
self.birth_year = birth_year or (datetime.now().year - current_age)
|
|
31
|
+
self.avatar_image = avatar_image
|
|
32
|
+
self.is_public = is_public
|
|
33
|
+
self.price = price
|
|
34
|
+
self.creator_id = creator_id
|
|
35
|
+
self.created_at = created_at or datetime.now().isoformat()
|
|
36
|
+
self.updated_at = updated_at or datetime.now().isoformat()
|
|
37
|
+
self.settings = {
|
|
38
|
+
"developer_mode": False,
|
|
39
|
+
"auto_organize": True,
|
|
40
|
+
"privacy_level": "private"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
44
|
+
return {
|
|
45
|
+
"avatar_id": self.avatar_id,
|
|
46
|
+
"name": self.name,
|
|
47
|
+
"description": self.description,
|
|
48
|
+
"personality_traits": self.personality_traits,
|
|
49
|
+
"current_age": self.current_age,
|
|
50
|
+
"birth_year": self.birth_year,
|
|
51
|
+
"avatar_image": self.avatar_image,
|
|
52
|
+
"is_public": self.is_public,
|
|
53
|
+
"price": self.price,
|
|
54
|
+
"creator_id": self.creator_id,
|
|
55
|
+
"created_at": self.created_at,
|
|
56
|
+
"updated_at": self.updated_at,
|
|
57
|
+
"settings": self.settings
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Avatar':
|
|
62
|
+
avatar = cls(
|
|
63
|
+
avatar_id=data.get("avatar_id"),
|
|
64
|
+
name=data.get("name", "虚拟形象"),
|
|
65
|
+
description=data.get("description", ""),
|
|
66
|
+
personality_traits=data.get("personality_traits"),
|
|
67
|
+
current_age=data.get("current_age", 25),
|
|
68
|
+
birth_year=data.get("birth_year"),
|
|
69
|
+
avatar_image=data.get("avatar_image"),
|
|
70
|
+
is_public=data.get("is_public", False),
|
|
71
|
+
price=data.get("price"),
|
|
72
|
+
creator_id=data.get("creator_id"),
|
|
73
|
+
created_at=data.get("created_at"),
|
|
74
|
+
updated_at=data.get("updated_at")
|
|
75
|
+
)
|
|
76
|
+
avatar.settings = data.get("settings", avatar.settings)
|
|
77
|
+
return avatar
|
|
78
|
+
|
|
79
|
+
def calculate_real_age(self) -> int:
|
|
80
|
+
return datetime.now().year - self.birth_year
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class AvatarManager:
|
|
84
|
+
def __init__(self, storage_dir: str = "avatar_data"):
|
|
85
|
+
self.storage_dir = storage_dir
|
|
86
|
+
self.avatars_dir = os.path.join(storage_dir, "avatars")
|
|
87
|
+
self.market_dir = os.path.join(storage_dir, "market")
|
|
88
|
+
|
|
89
|
+
for dir_path in [self.storage_dir, self.avatars_dir, self.market_dir]:
|
|
90
|
+
if not os.path.exists(dir_path):
|
|
91
|
+
os.makedirs(dir_path)
|
|
92
|
+
|
|
93
|
+
def _get_avatar_file(self, avatar_id: str) -> str:
|
|
94
|
+
return os.path.join(self.avatars_dir, f"{avatar_id}.json")
|
|
95
|
+
|
|
96
|
+
def create_avatar(
|
|
97
|
+
self,
|
|
98
|
+
name: str,
|
|
99
|
+
description: str = "",
|
|
100
|
+
personality_traits: List[str] = None,
|
|
101
|
+
current_age: int = 25,
|
|
102
|
+
creator_id: Optional[str] = None
|
|
103
|
+
) -> Avatar:
|
|
104
|
+
avatar = Avatar(
|
|
105
|
+
name=name,
|
|
106
|
+
description=description,
|
|
107
|
+
personality_traits=personality_traits,
|
|
108
|
+
current_age=current_age,
|
|
109
|
+
creator_id=creator_id
|
|
110
|
+
)
|
|
111
|
+
self.save_avatar(avatar)
|
|
112
|
+
return avatar
|
|
113
|
+
|
|
114
|
+
def save_avatar(self, avatar: Avatar):
|
|
115
|
+
avatar.updated_at = datetime.now().isoformat()
|
|
116
|
+
file_path = self._get_avatar_file(avatar.avatar_id)
|
|
117
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
118
|
+
json.dump(avatar.to_dict(), f, ensure_ascii=False, indent=2)
|
|
119
|
+
|
|
120
|
+
def load_avatar(self, avatar_id: str) -> Optional[Avatar]:
|
|
121
|
+
file_path = self._get_avatar_file(avatar_id)
|
|
122
|
+
if os.path.exists(file_path):
|
|
123
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
124
|
+
data = json.load(f)
|
|
125
|
+
return Avatar.from_dict(data)
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
def update_avatar(self, avatar_id: str, **kwargs) -> Optional[Avatar]:
|
|
129
|
+
avatar = self.load_avatar(avatar_id)
|
|
130
|
+
if not avatar:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
for key, value in kwargs.items():
|
|
134
|
+
if hasattr(avatar, key):
|
|
135
|
+
setattr(avatar, key, value)
|
|
136
|
+
|
|
137
|
+
self.save_avatar(avatar)
|
|
138
|
+
return avatar
|
|
139
|
+
|
|
140
|
+
def delete_avatar(self, avatar_id: str) -> bool:
|
|
141
|
+
file_path = self._get_avatar_file(avatar_id)
|
|
142
|
+
if os.path.exists(file_path):
|
|
143
|
+
os.remove(file_path)
|
|
144
|
+
return True
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
def list_avatars(self, creator_id: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
148
|
+
avatars = []
|
|
149
|
+
for filename in os.listdir(self.avatars_dir):
|
|
150
|
+
if filename.endswith(".json"):
|
|
151
|
+
file_path = os.path.join(self.avatars_dir, filename)
|
|
152
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
153
|
+
data = json.load(f)
|
|
154
|
+
if creator_id is None or data.get("creator_id") == creator_id:
|
|
155
|
+
avatars.append(data)
|
|
156
|
+
return avatars
|
|
157
|
+
|
|
158
|
+
def set_age(self, avatar_id: str, age: int) -> Optional[Avatar]:
|
|
159
|
+
avatar = self.load_avatar(avatar_id)
|
|
160
|
+
if avatar:
|
|
161
|
+
avatar.current_age = age
|
|
162
|
+
self.save_avatar(avatar)
|
|
163
|
+
return avatar
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
def get_memories_for_age(self, avatar_id: str, target_age: int) -> List[Dict[str, Any]]:
|
|
167
|
+
return tree_memory_system.get_memories_by_age(avatar_id, target_age)
|
|
168
|
+
|
|
169
|
+
def add_memory(
|
|
170
|
+
self,
|
|
171
|
+
avatar_id: str,
|
|
172
|
+
content: str,
|
|
173
|
+
min_age: int = 0,
|
|
174
|
+
max_age: int = 150,
|
|
175
|
+
clarity: int = 80,
|
|
176
|
+
emotional_tone: str = "neutral",
|
|
177
|
+
topic: Optional[str] = None
|
|
178
|
+
) -> str:
|
|
179
|
+
return tree_memory_system.add_memory(
|
|
180
|
+
avatar_id=avatar_id,
|
|
181
|
+
content=content,
|
|
182
|
+
min_age=min_age,
|
|
183
|
+
max_age=max_age,
|
|
184
|
+
clarity=clarity,
|
|
185
|
+
emotional_tone=emotional_tone,
|
|
186
|
+
topic=topic
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
def get_tree_structure(self, avatar_id: str) -> Optional[Dict[str, Any]]:
|
|
190
|
+
return tree_memory_system.get_tree_structure(avatar_id)
|
|
191
|
+
|
|
192
|
+
def toggle_developer_mode(self, avatar_id: str) -> Optional[bool]:
|
|
193
|
+
avatar = self.load_avatar(avatar_id)
|
|
194
|
+
if avatar:
|
|
195
|
+
avatar.settings["developer_mode"] = not avatar.settings["developer_mode"]
|
|
196
|
+
self.save_avatar(avatar)
|
|
197
|
+
return avatar.settings["developer_mode"]
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
def list_market_avatars(self) -> List[Dict[str, Any]]:
|
|
201
|
+
avatars = []
|
|
202
|
+
for filename in os.listdir(self.avatars_dir):
|
|
203
|
+
if filename.endswith(".json"):
|
|
204
|
+
file_path = os.path.join(self.avatars_dir, filename)
|
|
205
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
206
|
+
data = json.load(f)
|
|
207
|
+
if data.get("is_public") and data.get("price") is not None:
|
|
208
|
+
avatars.append(data)
|
|
209
|
+
return avatars
|
|
210
|
+
|
|
211
|
+
def purchase_avatar(self, avatar_id: str, buyer_id: str) -> Optional[Avatar]:
|
|
212
|
+
avatar = self.load_avatar(avatar_id)
|
|
213
|
+
if avatar and avatar.is_public and avatar.price is not None:
|
|
214
|
+
new_avatar = Avatar(
|
|
215
|
+
name=avatar.name,
|
|
216
|
+
description=avatar.description,
|
|
217
|
+
personality_traits=avatar.personality_traits.copy(),
|
|
218
|
+
current_age=avatar.current_age,
|
|
219
|
+
birth_year=avatar.birth_year,
|
|
220
|
+
creator_id=buyer_id
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
src_tree = tree_memory_system.load_tree(avatar_id)
|
|
224
|
+
tree_memory_system.save_tree(new_avatar.avatar_id, src_tree)
|
|
225
|
+
|
|
226
|
+
self.save_avatar(new_avatar)
|
|
227
|
+
return new_avatar
|
|
228
|
+
return None
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
avatar_manager = AvatarManager()
|