Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ OPENAI_API_KEY=your-openai-api-key
## PROMPT_SETTINGS_FILE - Specifies which Prompt Settings file to use (defaults to prompt_settings.yaml)
# PROMPT_SETTINGS_FILE=prompt_settings.yaml

## OPENAI_API_BASE_URL - Custom url for the OpenAI API, useful for connecting to custom backends. No effect if USE_AZURE is true, leave blank to keep the default url
## OPENAI_API_BASE_URL - Custom url for the OpenAI API, useful for connecting to custom backends. No effect if USE_AZURE is true, leave blank to keep the default url
# the following is an example:
# OPENAI_API_BASE_URL=http://localhost:443/v1

## OPENAI_FUNCTIONS - Enables OpenAI functions: https://platform.openai.com/docs/guides/gpt/function-calling
# the following is an example:
# OPENAI_FUNCTIONS=False

## AUTHORISE COMMAND KEY - Key to authorise commands
# AUTHORISE_COMMAND_KEY=y

Expand Down
8 changes: 6 additions & 2 deletions autogpt/agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ def signal_handler(signum, frame):
)

try:
assistant_reply_json = extract_json_from_response(assistant_reply)
assistant_reply_json = extract_json_from_response(
assistant_reply.content
)
validate_json(assistant_reply_json, self.config)
except json.JSONDecodeError as e:
logger.error(f"Exception while validating assistant reply JSON: {e}")
Expand All @@ -160,7 +162,9 @@ def signal_handler(signum, frame):
print_assistant_thoughts(
self.ai_name, assistant_reply_json, self.config
)
command_name, arguments = get_command(assistant_reply_json)
command_name, arguments = get_command(
assistant_reply_json, assistant_reply, self.config
)
if self.config.speak_mode:
say_text(f"I want to execute {command_name}")

Expand Down
8 changes: 6 additions & 2 deletions autogpt/agent/agent_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ def create_agent(
if plugin_messages := plugin.pre_instruction(messages.raw()):
messages.extend([Message(**raw_msg) for raw_msg in plugin_messages])
# Start GPT instance
agent_reply = create_chat_completion(prompt=messages, config=self.config)
agent_reply = create_chat_completion(
prompt=messages, config=self.config
).content

messages.add("assistant", agent_reply)

Expand Down Expand Up @@ -92,7 +94,9 @@ def message_agent(self, key: str | int, message: str) -> str:
messages.extend([Message(**raw_msg) for raw_msg in plugin_messages])

# Start GPT instance
agent_reply = create_chat_completion(prompt=messages, config=self.config)
agent_reply = create_chat_completion(
prompt=messages, config=self.config
).content

messages.add("assistant", agent_reply)

Expand Down
18 changes: 18 additions & 0 deletions autogpt/api/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import uvicorn

from autogpt.api.settings import settings


def main() -> None:
uvicorn.run(
"autogpt.api.application:get_app",
workers=settings.workers_count,
host=settings.host,
port=settings.port,
reload=settings.reload,
factory=settings.factory,
)


if __name__ == "__main__":
main()
46 changes: 46 additions & 0 deletions autogpt/api/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from pathlib import Path

from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
from fastapi.staticfiles import StaticFiles

from autogpt.api.lifetime import register_shutdown_event, register_startup_event
from autogpt.api.v1.router import api_router as api_router_v1

APP_ROOT = Path(__file__).parent


def get_app() -> FastAPI:
"""
Get FastAPI application.

This is the main constructor of an application.

:return: application.
"""

app = FastAPI(
title="autogpt",
version=1,
docs_url=None,
redoc_url=None,
openapi_url="/api/openapi.json",
default_response_class=ORJSONResponse,
)
# api_router.add_websocket_route("/ws", websocket_endpoint, name="websocket")
# Adds startup and shutdown events.
register_startup_event(app)
register_shutdown_event(app)

# Main router for the API.
app.include_router(router=api_router_v1, prefix="/api/v1")

# Adds static directory.
# This directory is used to access swagger files.
app.mount(
"/static",
StaticFiles(directory=APP_ROOT / "static"),
name="static",
)

return app
40 changes: 40 additions & 0 deletions autogpt/api/lifetime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import Awaitable, Callable

from fastapi import FastAPI


def register_startup_event(
app: FastAPI,
) -> Callable[[], Awaitable[None]]: # pragma: no cover
"""
Actions to run on application startup.

This function uses fastAPI app to store data
in the state, such as db_engine.

:param app: the fastAPI application.
:return: function that actually performs actions.
"""

@app.on_event("startup")
async def _startup() -> None: # noqa: WPS430
pass # noqa: WPS420

return _startup


def register_shutdown_event(
app: FastAPI,
) -> Callable[[], Awaitable[None]]: # pragma: no cover
"""
Actions to run on application's shutdown.

:param app: fastAPI application.
:return: function that actually performs actions.
"""

@app.on_event("shutdown")
async def _shutdown() -> None: # noqa: WPS430
pass # noqa: WPS420

return _shutdown
19 changes: 19 additions & 0 deletions autogpt/api/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from pydantic import BaseSettings


class Settings(BaseSettings):
"""
Application settings.

These parameters can be configured
with environment variables.
"""

host: str = "0.0.0.0"
port: int = 6060
workers_count: int = 1
reload: bool = True
factory: bool = True


settings = Settings()
1,804 changes: 1,804 additions & 0 deletions autogpt/api/static/docs/redoc.standalone.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions autogpt/api/static/docs/swagger-ui-bundle.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions autogpt/api/static/docs/swagger-ui.css

Large diffs are not rendered by default.

Empty file added autogpt/api/v1/__init__.py
Empty file.
Empty file.
29 changes: 29 additions & 0 deletions autogpt/api/v1/endpoints/agents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import uuid
from pathlib import Path

from fastapi import APIRouter
from pydantic.main import BaseModel

from autogpt.config import AIConfig, Config
from autogpt.memory.vector import get_memory
from autogpt.prompts.prompt import DEFAULT_TRIGGERING_PROMPT
from autogpt.workspace import Workspace
from tests.integration.agent_factory import get_command_registry

router = APIRouter()
class WorkspaceConfigRequest(BaseModel):
root: str
class WorkspaceRequest(BaseModel):
configuration: WorkspaceConfigRequest
class AgnosticAgentRequest(BaseModel):
workspace: WorkspaceRequest

class AgentRequest(AgnosticAgentRequest):
pass
@router.post("/agents")
async def create_agents(body: AgentRequest):
agent_id = uuid.uuid4().hex
return {
"agent_id": agent_id,
"workspace": body.workspace,
}
53 changes: 53 additions & 0 deletions autogpt/api/v1/endpoints/docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from fastapi import APIRouter, Request
from fastapi.openapi.docs import (
get_redoc_html,
get_swagger_ui_html,
get_swagger_ui_oauth2_redirect_html,
)
from fastapi.responses import HTMLResponse

router = APIRouter()


@router.get("/docs", include_in_schema=False)
async def swagger_ui_html(request: Request) -> HTMLResponse:
"""
Swagger UI.

:param request: current request.
:return: rendered swagger UI.
"""
title = request.app.title
return get_swagger_ui_html(
openapi_url=request.app.openapi_url,
title=f"{title} - Swagger UI",
oauth2_redirect_url=request.url_for("swagger_ui_redirect"),
swagger_js_url="/static/docs/swagger-ui-bundle.js",
swagger_css_url="/static/docs/swagger-ui.css",
)


@router.get("/swagger-redirect", include_in_schema=False)
async def swagger_ui_redirect() -> HTMLResponse:
"""
Redirect to swagger.

:return: redirect.
"""
return get_swagger_ui_oauth2_redirect_html()


@router.get("/redoc", include_in_schema=False)
async def redoc_html(request: Request) -> HTMLResponse:
"""
Redoc UI.

:param request: current request.
:return: rendered redoc UI.
"""
title = request.app.title
return get_redoc_html(
openapi_url=request.app.openapi_url,
title=f"{title} - ReDoc",
redoc_js_url="/static/docs/redoc.standalone.js",
)
12 changes: 12 additions & 0 deletions autogpt/api/v1/endpoints/health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from fastapi import APIRouter

router = APIRouter()


@router.get("/health")
def health_check() -> None:
"""
Checks the health of a project.

It returns 200 if the project is healthy.
"""
50 changes: 50 additions & 0 deletions autogpt/api/v1/endpoints/interactions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import uuid
from pathlib import Path

from fastapi import APIRouter
from pydantic.main import BaseModel

from autogpt.agent import Agent
from autogpt.api.v1.endpoints.agents import WorkspaceRequest
from autogpt.config import AIConfig, Config
from autogpt.memory.vector import get_memory
from autogpt.prompts.prompt import DEFAULT_TRIGGERING_PROMPT
from autogpt.workspace import Workspace
from tests.integration.agent_factory import get_command_registry

router = APIRouter()

class InteractionRequest(BaseModel):
workspace: WorkspaceRequest
user_input: str
@router.post("/agents/{agent_id}/interactions")
async def create_interactions(agent_id: str, body: InteractionRequest):
config = Config()
config.set_continuous_mode(False)
config.set_temperature(0)
config.plain_output = True
command_registry = get_command_registry(config)
config.memory_backend = "no_memory"
Workspace.build_file_logger_path(config, Path(body.workspace.configuration.root))
ai_config = AIConfig(
ai_name="Auto-GPT",
ai_role="a multi-purpose AI assistant.",
ai_goals=[body.user_input],
)

ai_config.command_registry = command_registry
system_prompt = ai_config.construct_full_prompt(config)

agent = Agent(
ai_name="File System Agent",
memory=get_memory(config),
command_registry=command_registry,
ai_config=ai_config,
config=config,
next_action_count=0,
system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
workspace_directory=body.workspace.configuration.root,
)

agent.start_interaction_loop()
48 changes: 48 additions & 0 deletions autogpt/api/v1/endpoints/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from pathlib import Path

from fastapi import APIRouter
from pydantic.main import BaseModel

from autogpt.agent import Agent
from autogpt.config import AIConfig, Config
from autogpt.memory.vector import get_memory
from autogpt.prompts.prompt import DEFAULT_TRIGGERING_PROMPT
from tests.integration.agent_factory import get_command_registry

router = APIRouter()


class Task(BaseModel):
content: str
workspace_location: str


@router.post("/tasks")
async def tasks(body: Task):
config = Config()
config.set_continuous_mode(True)
config.set_temperature(0)
config.plain_output = True
command_registry = get_command_registry(config)
config.memory_backend = "no_memory"

ai_config = AIConfig(
ai_name="Auto-GPT",
ai_role="a multi-purpose AI assistant.",
ai_goals=[body.content],
)
workspace_directory = Path(body.workspace_location)
ai_config.command_registry = command_registry
system_prompt = ai_config.construct_full_prompt(config)
agent = Agent(
ai_name="File System Agent",
memory=get_memory(config),
command_registry=command_registry,
ai_config=ai_config,
config=config,
next_action_count=0,
system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
workspace_directory=workspace_directory,
)
agent.start_interaction_loop()
10 changes: 10 additions & 0 deletions autogpt/api/v1/router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from fastapi.routing import APIRouter

from autogpt.api.v1.endpoints import docs, health, tasks, agents, interactions

api_router = APIRouter()
api_router.include_router(health.router)
api_router.include_router(docs.router)
api_router.include_router(tasks.router)
api_router.include_router(agents.router)
api_router.include_router(interactions.router)
Loading