Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

credentials.json

credentials/
**/credentials

**/bin

Expand Down
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
NPI_CMD_ROOT = $(shell pwd)
GIT_COMMIT = $(shell git log -1 --format='%h' | awk '{print $0}')
DOCKER_REGISTRY ?= 992297059634.dkr.ecr.us-west-2.amazonaws.com
DOCKER_PLATFORM ?= linux/arm64,linux/amd64
IMAGE_TAG ?= ${GIT_COMMIT}

build-docker-python:
docker buildx build --platform ${DOCKER_PLATFORM} \
-t npiai/python:3.12 -f build/base.Dockerfile build --push

build-docker-playground:
docker buildx build --platform ${DOCKER_PLATFORM} \
-t ${DOCKER_REGISTRY}/playground:${IMAGE_TAG} \
-f build/playground.Dockerfile . --push

release:
poetry publish --build -u __token__ -p ${PYPI_TOKEN}
rm -rf dist
15 changes: 0 additions & 15 deletions build/Dockerfile

This file was deleted.

47 changes: 0 additions & 47 deletions build/Makefile

This file was deleted.

2 changes: 1 addition & 1 deletion build/base.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM python:3.10
FROM --platform=$BUILDPLATFORM python:3.12

LABEL maintainer="Wenfeng Wang <[email protected]>"

Expand Down
7 changes: 0 additions & 7 deletions build/builder/py312.Dockerfile

This file was deleted.

15 changes: 0 additions & 15 deletions build/gateway.Dockerfile

This file was deleted.

14 changes: 14 additions & 0 deletions build/playground.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM --platform=$BUILDPLATFORM npiai/python:3.12

LABEL maintainer="Wenfeng Wang <[email protected]>"

COPY . /npi/

WORKDIR /npi

RUN poetry install
ENV PATH="/root/.cache/pypoetry/virtualenvs/npiai-Gwe6qz7c-py3.11/bin:${PATH}"
RUN playwright install-deps chromium
RUN playwright install chromium

ENTRYPOINT ["python", "playground/main.py"]
2 changes: 1 addition & 1 deletion build/playwright/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ setuptools = "^69.2.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
build-backend = "poetry.core.masonry.api"
2 changes: 1 addition & 1 deletion npiai/context/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class Context:
__active_tool: Union['BaseTool', None] = None
__last_screenshot: str | None = None

def __init__(self, instruction: str) -> None:
def __init__(self, instruction: str | None = None) -> None:
self.id = str(uuid.uuid4())
self.born_at = datetime.datetime.now()
self.history: List[ThreadMessage | str] = []
Expand Down
4 changes: 2 additions & 2 deletions npiai/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ def server(self):
...

@abstractmethod
async def start(self):
async def start(self, ctx: Context | None = None):
"""Start the tools"""
...

@abstractmethod
async def end(self):
async def end(self, ctx: Context | None = None):
"""Stop and dispose the tools"""
...

Expand Down
4 changes: 2 additions & 2 deletions npiai/core/browser/navigator.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ def __init__(
self.max_steps = max_steps

# navigator uses shared playwright context, so we don't need to start it again here
async def start(self):
async def start(self, ctx: Context | None = None):
pass

async def end(self):
async def end(self, ctx: Context | None = None):
pass

async def generate_user_prompt(self, task: str, history: List[Response]):
Expand Down
23 changes: 10 additions & 13 deletions npiai/core/tool/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import sys
from typing import List, overload

from litellm.types.completion import ChatCompletionMessageParam
from fastapi import FastAPI, Request

import uvicorn
from npiai.llm import LLM, OpenAI
from npiai.utils import logger
from npiai.types import FunctionRegistration
from npiai.context import Context, ThreadMessage
from npiai.core import callback
Expand All @@ -33,7 +31,6 @@ def unpack_functions(self) -> List[FunctionRegistration]:
# Wrap the chat function of this agent to FunctionRegistration

def chat(message: str, ctx: Context):
# TODO: pass thread down
return self.chat(message, ctx)

fn_reg = FunctionRegistration(
Expand All @@ -59,11 +56,11 @@ def use_hitl(self, hitl: HITL):
# super().use_hitl(hitl)
self._tool.use_hitl(hitl)

async def start(self):
await self._tool.start()
async def start(self, ctx: Context | None = None):
await self._tool.start(ctx)

async def end(self):
await self._tool.end()
async def end(self, ctx: Context | None = None):
await self._tool.end(ctx)

async def server(self):
"""Start the server"""
Expand Down Expand Up @@ -91,12 +88,12 @@ def signal_handler(sig, frame):
async def chat(
self,
message: str,
thread: Context = None,
ctx: Context = None,
) -> str:
if thread is None:
thread = Context('')
if ctx is None:
ctx = Context()

msg = thread.fork(message)
msg = ctx.fork(message)
if self._tool.system_prompt:
msg.append(
{
Expand All @@ -112,7 +109,7 @@ async def chat(
}
)

return await self._call_llm(thread, msg)
return await self._call_llm(ctx, msg)

async def _call_llm(self, thread: Context, message: ThreadMessage) -> str:
while True:
Expand Down Expand Up @@ -158,7 +155,7 @@ async def chat(
ctx: Context = None,
) -> str:
if ctx is None:
ctx = Context('')
ctx = Context()

if not self._tool.use_screenshot:
return await super().chat(message, ctx)
Expand Down
9 changes: 5 additions & 4 deletions npiai/core/tool/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from npiai.core.tool.function import FunctionTool, function
from npiai.core.browser.playwright import PlaywrightContext
from npiai.context import Context


class MdConverter(MarkdownConverter):
Expand Down Expand Up @@ -49,15 +50,15 @@ async def get_text(self):
html = await self.playwright.page.evaluate('() => document.body.innerHTML')
return MdConverter().convert(html)

async def start(self):
async def start(self, ctx: Context | None = None):
"""Start the Browser App"""
if not self._started:
await super().start()
await super().start(ctx)
await self.playwright.start()

async def end(self):
async def end(self, ctx: Context | None = None):
"""Dispose the chrome tools"""
await super().end()
await super().end(ctx)
await self.playwright.stop()

async def goto_blank(self):
Expand Down
21 changes: 11 additions & 10 deletions npiai/core/tool/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ def use_hitl(self, hitl: HITL):
for app in self._sub_tools:
app.use_hitl(hitl)

async def start(self):
async def start(self, ctx: Context | None = None):
"""Start the tools"""
if not self._started:
self._started = True
for tool in self._sub_tools:
await tool.start()
await tool.start(ctx)

def server(self):
"""Start the server"""
Expand All @@ -161,14 +161,15 @@ def convert_camel_to_snake(name: str) -> str:
@fapp.api_route("/{full_path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
async def root(full_path: str, request: Request):
method = convert_camel_to_snake(full_path)
ctx = Context(instruction="")
try:
match request.method:
case "POST":
args = await request.json()
res = await self._exec(method, args)
res = await self._exec(ctx, method, args)
case "GET":
args = {k: v for k, v in request.query_params.items()}
res = await self._exec(method, args)
res = await self._exec(ctx, method, args)
case _:
return JSONResponse({'error': 'Method not allowed'}, status_code=405)
try:
Expand Down Expand Up @@ -198,12 +199,12 @@ def signal_handler(sig, frame):

uvicorn.run(fapp, host="0.0.0.0", port=18000)

async def end(self):
async def end(self, ctx: Context | None = None):
"""Stop and dispose the tools"""
if self._started:
self._started = False
for app in self._sub_tools:
await app.end()
await app.end(ctx)

def add_tool(
self,
Expand All @@ -223,8 +224,8 @@ def add_tool(
async def debug(self, app_name: str = None, fn_name: str = None, args: Dict[str, Any] = None) -> str:
if app_name:
fn_name = f'{app_name}_{fn_name}'
ctx = Context('')
return await self._exec(ctx, fn_name, args)

return await self._exec(Context(), fn_name, args)

async def call(
self,
Expand Down Expand Up @@ -254,7 +255,8 @@ async def call(
res = await self._exec(ctx, fn_name, args)
except Exception as e:
logger.error(e)
await ctx.send_msg(callback.Callable(f'Exception while executing {fn_name}: {e}'))
res = f'Exception while executing {fn_name}: {e}'
await ctx.send_msg(callback.Callable(res))

logger.debug(f'[{self.name}]: function `{fn_name}` returned: {res}')

Expand Down Expand Up @@ -282,7 +284,6 @@ async def _exec(self, ctx: Context, fn_name: str, args: Dict[str, Any] = None) -
args = {tool.ctx_param_name: ctx}
else:
args[tool.ctx_param_name] = ctx

if args is None:
return str(await tool.fn())
return str(await tool.fn(**args))
Expand Down
9 changes: 5 additions & 4 deletions npiai/tools/discord/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import discord

from npiai.context import Context
from npiai.utils import logger
from npiai import FunctionTool, function
from npiai.error.auth import UnauthorizedError
Expand Down Expand Up @@ -54,12 +55,12 @@ def __init__(self, access_token: str = None):
self.client = discord.Client(intents=discord.Intents.default())
self._access_token = token

async def start(self):
await super().start()
async def start(self, ctx: Context | None = None):
await super().start(ctx)
await self.client.login(self._access_token)

async def end(self):
await super().end()
async def end(self, ctx: Context | None = None):
await super().end(ctx)
await self.client.close()

def parse_user(self, user: discord.User):
Expand Down
Loading