Files
AutoGPT-Code-Ability/codex/develop/agent.py
T
0ca37c25d6 Fix unimplemented function semantic (#58)
* Fix unimplemented function semantic

---------

Co-authored-by: majdyz <[email protected]>
Co-authored-by: majdyz <[email protected]>
Co-authored-by: Swifty <[email protected]>
2024-02-27 12:00:34 +01:00

145 lines
5.0 KiB
Python

import asyncio
import logging
import os
from prisma.enums import FunctionState
from prisma.models import APIRouteSpec, CompletedApp, Function, Specification
from codex.api_model import Identifiers
from codex.develop.compile import compile_route, create_app
from codex.develop.develop import DevelopAIBlock
RECURSION_DEPTH_LIMIT = int(os.environ.get("RECURSION_DEPTH_LIMIT", 3))
logger = logging.getLogger(__name__)
async def develop_application(ids: Identifiers, spec: Specification) -> CompletedApp:
"""
Develops an application based on the given identifiers and specification.
Args:
ids (Identifiers): The identifiers used for development.
spec (Specification): The specification of the application.
Returns:
CompletedApp: The completed application.
"""
compiled_routes = []
if spec.ApiRouteSpecs:
for api_route in spec.ApiRouteSpecs:
route_root_func = await develop_route(
[], ids, api_route, api_route.description, api_route.functionName
)
logger.info(f"Route function id: {route_root_func.id}")
compiled_route = await compile_route(ids, route_root_func, api_route)
compiled_routes.append(compiled_route)
return await create_app(ids, spec, compiled_routes)
async def develop_route(
generated_functions: list[
Function
], # TODO: remove this, replace with vector-lookup.
ids: Identifiers,
api_route: APIRouteSpec,
goal_description: str,
function_name: str,
function_id: str = None,
function_template: str = None,
depth: int = 0,
) -> Function:
"""
Recursively develops a function and its child functions
based on the provided function definition and api route spec.
Args:
generated_functions (list[Function]): The list of already generated functions, used to promote function re-use.
ids (Identifiers): The identifiers for the function.
api_route (APIRouteSpec): The API route specification.
goal_description (str): The high-level goal of the function to create.
function_name (str): The name of the function to create.
function_id (str): The id of the function to create. If not provided, a new root-function will be created.
function_template (str): The docstring/template of the function to create.
depth (int): The depth of the recursion.
Returns:
Function: The developed route function.
"""
logger.info(
f"Developing for route: {api_route.path} - Func: {function_name}, depth: {depth}"
)
if depth >= RECURSION_DEPTH_LIMIT:
raise ValueError("Recursion depth exceeded")
route_function: Function = await DevelopAIBlock().invoke(
ids=ids,
invoke_params={
"function_name": function_name,
"goal": goal_description,
"function_signature": function_template,
"provided_functions": [
f.template
for f in generated_functions
if f.functionName != function_name and f.parentFunctionId
],
# api_route is not used by the prompt, but is used by the function
"api_route": api_route,
# function_id is used, so we can update the function with the implementation
"function_id": function_id,
"allow_stub": depth < RECURSION_DEPTH_LIMIT,
},
)
if route_function.ChildFunction:
generated_functions.extend(route_function.ChildFunction)
logger.info(f"\tDeveloping {len(route_function.ChildFunction)} child functions")
tasks = [
develop_route(
ids=ids,
goal_description=goal_description,
function_id=child.id,
function_name=child.functionName,
function_template=child.template,
api_route=api_route,
depth=depth + 1,
generated_functions=generated_functions,
)
for child in route_function.ChildFunction
if child.state == FunctionState.DEFINITION
]
await asyncio.gather(*tasks)
else:
logger.info(f"❌ No child functions to develop")
logger.debug(route_function.rawCode)
return route_function
if __name__ == "__main__":
import asyncio
import prisma
from prisma.models import APIRouteSpec
import codex.common.test_const as test_consts
from codex.common.ai_model import OpenAIChatClient
from codex.common.logging import setup_logging
from codex.requirements.database import get_latest_specification
OpenAIChatClient.configure({})
setup_logging(local=True)
client = prisma.Prisma(auto_register=True)
async def run_me():
await client.connect()
ids = test_consts.identifier_1
spec = await get_latest_specification(ids.user_id, ids.app_id)
ans = await develop_application(ids=ids, spec=spec)
await client.disconnect()
return ans
ans = asyncio.run(run_me())
logger.info(ans)