Spaces:
Sleeping
Sleeping
🍌🐒
commited on
Commit
·
beb52ea
1
Parent(s):
dab7e4c
Add simplified source files for Hugging Face Space
Browse files- src/__init__.py +5 -0
- src/agents.py +58 -0
- src/config.py +44 -0
- src/logger.py +40 -0
- src/project.py +34 -0
- src/state.py +14 -0
src/__init__.py
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Devika AI Assistant - A powerful AI coding assistant
|
3 |
+
"""
|
4 |
+
|
5 |
+
__version__ = "0.1.0"
|
src/agents.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from typing import Optional
|
3 |
+
import openai
|
4 |
+
import anthropic
|
5 |
+
from duckduckgo_search import DDGS
|
6 |
+
|
7 |
+
class Agent:
|
8 |
+
def __init__(self, base_model: str = "gpt-3.5-turbo", search_engine: str = "duckduckgo"):
|
9 |
+
self.base_model = base_model
|
10 |
+
self.search_engine = search_engine
|
11 |
+
|
12 |
+
# Initialize API clients
|
13 |
+
if "gpt" in base_model:
|
14 |
+
openai.api_key = os.getenv("OPENAI_API_KEY")
|
15 |
+
elif "claude" in base_model:
|
16 |
+
self.claude = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
|
17 |
+
|
18 |
+
def execute(self, message: str, project_name: str) -> Optional[str]:
|
19 |
+
try:
|
20 |
+
# Process the message based on the selected model
|
21 |
+
if "gpt" in self.base_model:
|
22 |
+
response = self._process_with_gpt(message)
|
23 |
+
elif "claude" in self.base_model:
|
24 |
+
response = self._process_with_claude(message)
|
25 |
+
else:
|
26 |
+
response = "Unsupported model selected"
|
27 |
+
|
28 |
+
return response
|
29 |
+
except Exception as e:
|
30 |
+
return f"Error processing message: {str(e)}"
|
31 |
+
|
32 |
+
def subsequent_execute(self, message: str, project_name: str) -> Optional[str]:
|
33 |
+
return self.execute(message, project_name)
|
34 |
+
|
35 |
+
def _process_with_gpt(self, message: str) -> str:
|
36 |
+
response = openai.chat.completions.create(
|
37 |
+
model=self.base_model,
|
38 |
+
messages=[{"role": "user", "content": message}]
|
39 |
+
)
|
40 |
+
return response.choices[0].message.content
|
41 |
+
|
42 |
+
def _process_with_claude(self, message: str) -> str:
|
43 |
+
message = anthropic.Message(
|
44 |
+
role="user",
|
45 |
+
content=message
|
46 |
+
)
|
47 |
+
response = self.claude.messages.create(
|
48 |
+
model="claude-3-opus-20240229",
|
49 |
+
messages=[message]
|
50 |
+
)
|
51 |
+
return response.content[0].text
|
52 |
+
|
53 |
+
def _search_web(self, query: str, num_results: int = 5) -> list:
|
54 |
+
if self.search_engine == "duckduckgo":
|
55 |
+
with DDGS() as ddgs:
|
56 |
+
return list(ddgs.text(query, max_results=num_results))
|
57 |
+
# Add support for other search engines as needed
|
58 |
+
return []
|
src/config.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
from pathlib import Path
|
4 |
+
|
5 |
+
class Config:
|
6 |
+
_instance = None
|
7 |
+
|
8 |
+
def __new__(cls):
|
9 |
+
if cls._instance is None:
|
10 |
+
cls._instance = super().__new__(cls)
|
11 |
+
cls._instance._load_config()
|
12 |
+
return cls._instance
|
13 |
+
|
14 |
+
def _load_config(self):
|
15 |
+
self.config = {
|
16 |
+
"API_KEYS": {
|
17 |
+
"OPENAI": os.getenv("OPENAI_API_KEY", ""),
|
18 |
+
"ANTHROPIC": os.getenv("ANTHROPIC_API_KEY", ""),
|
19 |
+
"BING": os.getenv("BING_API_KEY", ""),
|
20 |
+
"GOOGLE_SEARCH": os.getenv("GOOGLE_API_KEY", ""),
|
21 |
+
"GOOGLE_SEARCH_ENGINE_ID": os.getenv("GOOGLE_SEARCH_ENGINE_ID", ""),
|
22 |
+
},
|
23 |
+
"API_ENDPOINTS": {
|
24 |
+
"BING": "https://api.bing.microsoft.com/v7.0/search",
|
25 |
+
"GOOGLE": "https://www.googleapis.com/customsearch/v1",
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
# Create necessary directories
|
30 |
+
base_dir = Path("/code")
|
31 |
+
for dir_name in ["db", "logs", "projects", "screenshots", "pdfs"]:
|
32 |
+
(base_dir / dir_name).mkdir(exist_ok=True)
|
33 |
+
|
34 |
+
def get_config(self):
|
35 |
+
return self.config
|
36 |
+
|
37 |
+
def get_bing_api_key(self):
|
38 |
+
return self.config["API_KEYS"]["BING"]
|
39 |
+
|
40 |
+
def get_google_search_api_key(self):
|
41 |
+
return self.config["API_KEYS"]["GOOGLE_SEARCH"]
|
42 |
+
|
43 |
+
def get_google_search_engine_id(self):
|
44 |
+
return self.config["API_KEYS"]["GOOGLE_SEARCH_ENGINE_ID"]
|
src/logger.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
from pathlib import Path
|
3 |
+
|
4 |
+
class Logger:
|
5 |
+
def __init__(self, filename="devika_agent.log"):
|
6 |
+
# Set up logging
|
7 |
+
self.log_dir = Path("/code/logs")
|
8 |
+
self.log_dir.mkdir(exist_ok=True)
|
9 |
+
self.log_file = self.log_dir / filename
|
10 |
+
|
11 |
+
# Configure logging
|
12 |
+
logging.basicConfig(
|
13 |
+
level=logging.INFO,
|
14 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
15 |
+
handlers=[
|
16 |
+
logging.FileHandler(self.log_file),
|
17 |
+
logging.StreamHandler()
|
18 |
+
]
|
19 |
+
)
|
20 |
+
self.logger = logging.getLogger("devika")
|
21 |
+
|
22 |
+
def info(self, message: str):
|
23 |
+
self.logger.info(message)
|
24 |
+
|
25 |
+
def error(self, message: str):
|
26 |
+
self.logger.error(message)
|
27 |
+
|
28 |
+
def warning(self, message: str):
|
29 |
+
self.logger.warning(message)
|
30 |
+
|
31 |
+
def debug(self, message: str):
|
32 |
+
self.logger.debug(message)
|
33 |
+
|
34 |
+
def route_logger(logger):
|
35 |
+
def decorator(f):
|
36 |
+
def wrapper(*args, **kwargs):
|
37 |
+
logger.info(f"Route called: {f.__name__}")
|
38 |
+
return f(*args, **kwargs)
|
39 |
+
return wrapper
|
40 |
+
return decorator
|
src/project.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from datetime import datetime
|
3 |
+
from pathlib import Path
|
4 |
+
|
5 |
+
class ProjectManager:
|
6 |
+
def __init__(self):
|
7 |
+
self.projects_dir = Path("/code/projects")
|
8 |
+
self.projects_dir.mkdir(exist_ok=True)
|
9 |
+
self.messages = {}
|
10 |
+
|
11 |
+
def new_message(self):
|
12 |
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
13 |
+
return {
|
14 |
+
"from_devika": True,
|
15 |
+
"message": None,
|
16 |
+
"timestamp": timestamp
|
17 |
+
}
|
18 |
+
|
19 |
+
def get_messages(self, project_name: str):
|
20 |
+
if project_name not in self.messages:
|
21 |
+
self.messages[project_name] = []
|
22 |
+
return self.messages[project_name]
|
23 |
+
|
24 |
+
def add_message(self, project_name: str, message: str, from_devika: bool = True):
|
25 |
+
if project_name not in self.messages:
|
26 |
+
self.messages[project_name] = []
|
27 |
+
|
28 |
+
msg = {
|
29 |
+
"from_devika": from_devika,
|
30 |
+
"message": message,
|
31 |
+
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
32 |
+
}
|
33 |
+
self.messages[project_name].append(msg)
|
34 |
+
return msg
|
src/state.py
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class AgentState:
|
2 |
+
def __init__(self):
|
3 |
+
self.states = {}
|
4 |
+
|
5 |
+
def get_latest_state(self, project_name: str):
|
6 |
+
return self.states.get(project_name, None)
|
7 |
+
|
8 |
+
def is_agent_completed(self, project_name: str):
|
9 |
+
state = self.get_latest_state(project_name)
|
10 |
+
return state.get("completed", True) if state else True
|
11 |
+
|
12 |
+
def is_agent_active(self, project_name: str):
|
13 |
+
state = self.get_latest_state(project_name)
|
14 |
+
return state.get("agent_is_active", False) if state else False
|