Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

archgw cli #117

Merged
merged 11 commits into from
Oct 4, 2024
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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ demos/employee_details_copilot/ollama/models/
demos/employee_details_copilot_arch/ollama/models/
demos/network_copilot/ollama/models/
arch_log/
arch/tools/*.egg-info
arch/tools/config
2 changes: 1 addition & 1 deletion arch/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ COPY --from=envoy /usr/local/bin/envoy /usr/local/bin/envoy
WORKDIR /config
COPY arch/requirements.txt .
RUN pip install -r requirements.txt
COPY arch/config_generator.py .
COPY arch/tools/config_generator.py .
COPY arch/envoy.template.yaml .
COPY arch/arch_config_schema.yaml .

Expand Down
88 changes: 0 additions & 88 deletions arch/config_generator.py

This file was deleted.

17 changes: 9 additions & 8 deletions arch/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
services:
archgw:
build:
context: ../
dockerfile: arch/Dockerfile
image: archgw:latest
ports:
- "10000:10000"
- "18080:9901"
- "19901:9901"
volumes:
- ${ARCH_CONFIG_FILE}:/config/arch_config.yaml
- ${ARCH_CONFIG_FILE:-./demos/function_calling/arch_confg.yaml}:/config/arch_config.yaml
- /etc/ssl/cert.pem:/etc/ssl/cert.pem
- ./arch_log:/var/log/
depends_on:
model_server:
condition: service_healthy

model_server:
build:
context: ../model_server
dockerfile: Dockerfile
image: model_server:latest
ports:
- "18081:80"
healthcheck:
Expand All @@ -26,3 +22,8 @@ services:
retries: 20
volumes:
- ~/.cache/huggingface:/root/.cache/huggingface
environment:
- OLLAMA_ENDPOINT=${OLLAMA_ENDPOINT:-host.docker.internal}
- OLLAMA_MODEL=Arch-Function-Calling-3B-Q4_K_M
- MODE=${MODE:-cloud}
- FC_URL=${FC_URL:-https://arch-fc-free-trial-4mzywewe.uc.gateway.dev/v1}
3 changes: 2 additions & 1 deletion arch/envoy.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ static_resources:
{% else -%}
connect_timeout: 5s
{% endif -%}
type: STRICT_DNS
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: {{ cluster.name }}
Expand Down
2 changes: 1 addition & 1 deletion arch/src/stream_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ impl StreamContext {
if messages.len() >= 2 {
let latest_assistant_message = &messages[messages.len() - 2];
if let Some(model) = latest_assistant_message.model.as_ref() {
if model.starts_with("Arch") {
if model.contains("Arch") {
arch_assistant = true;
}
}
Expand Down
2 changes: 2 additions & 0 deletions arch/tools/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include config/docker-compose.yaml
include config/arch_config_schema.yaml
28 changes: 28 additions & 0 deletions arch/tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Setup Instructions: archgw CLI

This guide will walk you through the steps to set up the archgw cli on your local machine

### Step 1: Create a Python virtual environment

In the tools directory, create a Python virtual environment by running:

```bash
python -m venv venv
```

### Step 2: Activate the virtual environment
* On Linux/MacOS:

```bash
source venv/bin/activate
```

### Step 3: Run the build script
```bash
sh build-cli.sh
```

## Uninstall Instructions: archgw CLI
```bash
pip uninstall archgw
```
Empty file added arch/tools/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions arch/tools/build-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

# Define paths
source_schema="../arch_config_schema.yaml"
source_compose="../docker-compose.yaml"
destination_dir="config"

# Ensure the destination directory exists only if it doesn't already
if [ ! -d "$destination_dir" ]; then
mkdir -p "$destination_dir"
echo "Directory $destination_dir created."
fi

# Copy the files
cp "$source_schema" "$destination_dir/arch_config_schema.yaml"
cp "$source_compose" "$destination_dir/docker-compose.yaml"

# Print success message
echo "Files copied successfully!"

echo "Building the cli"
pip install -e .
117 changes: 117 additions & 0 deletions arch/tools/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import click
from core import start_arch, stop_arch
import targets
import os
import config_generator
import pkg_resources
import sys
import subprocess

logo = r"""
_ _
/ \ _ __ ___ | |__
/ _ \ | '__|/ __|| '_ \
/ ___ \ | | | (__ | | | |
/_/ \_\|_| \___||_| |_|

"""
@click.group(invoke_without_command=True)
@click.pass_context
def main(ctx):
if ctx.invoked_subcommand is None:
click.echo( """Arch (The Intelligent Prompt Gateway) CLI""")
click.echo(logo)
click.echo(ctx.get_help())

# Command to build archgw and model_server Docker images
ARCHGW_DOCKERFILE = "./arch/Dockerfile"
MODEL_SERVER_DOCKERFILE = "./model_server/Dockerfile"

@click.command()
def build():
"""Build Arch from source. Must be in root of cloned repo."""
# Check if /arch/Dockerfile exists
if os.path.exists(ARCHGW_DOCKERFILE):
click.echo("Building archgw image...")
try:
subprocess.run(["docker", "build", "-f", ARCHGW_DOCKERFILE, "-t", "archgw:latest", "."], check=True)
click.echo("archgw image built successfully.")
except subprocess.CalledProcessError as e:
click.echo(f"Error building archgw image: {e}")
sys.exit(1)
else:
click.echo("Error: Dockerfile not found in /arch")
sys.exit(1)

# Check if /model_server/Dockerfile exists
if os.path.exists(MODEL_SERVER_DOCKERFILE):
click.echo("Building model_server image...")
try:
subprocess.run(["docker", "build", "-f", MODEL_SERVER_DOCKERFILE, "-t", "model_server:latest", "./model_server"], check=True)
click.echo("model_server image built successfully.")
except subprocess.CalledProcessError as e:
click.echo(f"Error building model_server image: {e}")
sys.exit(1)
else:
click.echo("Error: Dockerfile not found in /model_server")
sys.exit(1)

click.echo("All images built successfully.")

@click.command()
@click.argument('file', required=False) # Optional file argument
@click.option('-path', default='.', help='Path to the directory containing arch_config.yml')
def up(file, path):
"""Starts Arch."""
if file:
# If a file is provided, process that file
arch_config_file = os.path.abspath(file)
else:
# If no file is provided, use the path and look for arch_config.yml
arch_config_file = os.path.abspath(os.path.join(path, "arch_config.yml"))

# Check if the file exists
if not os.path.exists(arch_config_file):
print(f"Error: {arch_config_file} does not exist.")
return

print(f"Processing config file: {arch_config_file}")
arch_schema_config = pkg_resources.resource_filename(__name__, "config/arch_config_schema.yaml")

print(f"Validating {arch_config_file}")

try:
config_generator.validate_prompt_config(arch_config_file=arch_config_file, arch_config_schema_file=arch_schema_config)
except Exception as e:
print("Exiting archgw up")
sys.exit(1)

print("Starting Arch gateway and Arch model server services via docker ")
start_arch(arch_config_file)

@click.command()
def down():
"""Stops Arch."""
stop_arch()

@click.command()
@click.option('-f', '--file', type=click.Path(exists=True), required=True, help="Path to the Python file")
def generate_prompt_targets(file):
"""Generats prompt_targets from python methods.
Note: This works for simple data types like ['int', 'float', 'bool', 'str', 'list', 'tuple', 'set', 'dict']:
If you have a complex pydantic data type, you will have to flatten those manually until we add support for it."""

print(f"Processing file: {file}")
if not file.endswith(".py"):
print("Error: Input file must be a .py file")
sys.exit(1)

targets.generate_prompt_targets(file)

main.add_command(up)
main.add_command(down)
main.add_command(build)
main.add_command(generate_prompt_targets)

if __name__ == '__main__':
main()
Loading
Loading