Skip to content

feat: setup docker file #705

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

Closed
wants to merge 2 commits into from
Closed
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
Empty file added .env.example
Empty file.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,7 @@ cython_debug/
# PyPI configuration file
.pypirc
.aider*

# VS Code settings
launch.json
mcp.json
28 changes: 28 additions & 0 deletions .run/Run Dev.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run Dev" type="Python.FastAPI">
<option name="file" value="$PROJECT_DIR$/app/main.py" />
<module name="data-multiagents" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="$PROJECT_DIR$/venv/bin/python" />
<option name="SDK_NAME" value="Python 3.9 (data-multiagents)" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<EXTENSION ID="net.ashald.envfile">
<option name="IS_ENABLED" value="false" />
<option name="IS_SUBST" value="false" />
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
<option name="IS_IGNORE_MISSING_FILES" value="false" />
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
<ENTRIES>
<ENTRY IS_ENABLED="true" PARSER="runconfig" IS_EXECUTABLE="false" />
</ENTRIES>
</EXTENSION>
<option name="launchJavascriptDebuger" value="false" />
<method v="2" />
</configuration>
</component>
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM python:3.10-slim

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app


CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
74 changes: 74 additions & 0 deletions app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# OpenAI Agents API

This project provides a FastAPI application that exposes OpenAI agents through a RESTful API.

## Features

- FastAPI-based RESTful API for OpenAI agents
- Development server with hot-reloading

## Requirements

- Python 3.8+
- Required packages are listed in `requirements.txt`

## Setup

1. Run the development server:

```bash
./dev_appserver.py --reload
```

This will start the server at http://127.0.0.1:8000

## API Endpoints

### Weather Agent

- `GET /weather/cities`: Get a list of available cities
- Returns: `{"NEW_YORK": "New York", "LONDON": "London", "TOKYO": "Tokyo", "SYDNEY": "Sydney"}`

- `GET /weather/{city}`: Get weather data for a specific city
- Example: `GET /weather/NEW_YORK`
- Returns: `{"city": "New York", "temperature_range": "15-25°C", "conditions": "Partly cloudy"}`

- `POST /weather/ask`: Ask the weather agent a question
- Request body: `{"query": "What's the weather in Tokyo?", "city": "TOKYO"}`
- Returns: `{"response": "The weather in Tokyo is currently sunny, with a temperature range of 20-30°C.", "weather_data": {...}, "trace_id": "..."}`

- `POST /weather/stream`: Stream a response from the weather agent
- Request body: `{"query": "What's the weather in Tokyo?", "stream": true, "city": "TOKYO"}`

### Other Endpoints

- `GET /`: Root endpoint
- `GET /health`: Health check endpoint

## Example Usage

### Using curl

```bash
# Get a list of cities
curl http://localhost:8000/weather/cities

# Get weather for a specific city
curl http://localhost:8000/weather/NEW_YORK

# Ask the weather agent a question
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "What is the weather like in Tokyo?"}' \
http://localhost:8000/weather/ask

# Stream a response from the weather agent
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "Tell me about London weather", "stream": true}' \
http://localhost:8000/weather/stream
```

## Extending

### Adding More Agents

To add more agents, create new router files in the `app/routers` directory and include them in `app/__init__.py`.
Empty file added app/__init__.py
Empty file.
42 changes: 42 additions & 0 deletions app/config/logging_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"default": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "default",
"stream": "ext://sys.stdout"
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "DEBUG",
"formatter": "default",
"filename": "app.log",
"maxBytes": 10485760,
"backupCount": 5
}
},
"loggers": {
"uvicorn": {
"handlers": ["console"],
"level": "INFO"
},
"app": {
"handlers": ["console", "file"],
"level": "DEBUG",
"propagate": false
}
},
"root": {
"level": "DEBUG",
"handlers": ["console"],
"propagate": false
}
}
56 changes: 56 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import json
import logging.config

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.routers import weather_agent

# Set up logging
with open("app/config/logging_config.json", "r") as config_file:
logging_config = json.load(config_file)

logging.config.dictConfig(logging_config)
logger = logging.getLogger(__name__)

# Create the FastAPI app
app = FastAPI(
title="Weather API with GPT-4.1",
description="An API that uses GPT-4.1 to provide weather information for cities",
version="1.0.0",
)

# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=[
"*"
], # For development. In production, specify the allowed origins
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# Register routers
app.include_router(weather_agent.router)

@app.get("/")
async def root():
"""
Root endpoint that returns a simple welcome message.

Returns:
A welcome message
"""
return {"message": "Welcome to the Weather API with GPT-4.1"}


@app.get("/health")
async def health_check():
"""
Health check endpoint.

Returns:
Health status
"""
return {"status": "ok"}
Empty file added app/models/__init__.py
Empty file.
86 changes: 86 additions & 0 deletions app/models/weather.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from enum import auto
from typing import Optional

from pydantic import BaseModel
from strenum import StrEnum


class City(StrEnum):
"""Enum of cities supported by the weather agent."""

NEW_YORK = auto()
LONDON = auto()
TOKYO = auto()
SYDNEY = auto()

@classmethod
def get_display_name(cls, city: "City") -> str:
"""Get the display name for a city."""
display_names = {
cls.NEW_YORK: "New York",
cls.LONDON: "London",
cls.TOKYO: "Tokyo",
cls.SYDNEY: "Sydney",
}
return display_names.get(city, str(city))


class WeatherData(BaseModel):
"""Weather data model."""

city: str
temperature_range: str
conditions: str

@classmethod
def from_city_enum(cls, city: City) -> "WeatherData":
"""Create a WeatherData instance from a City enum."""
# Mock weather data for each city
weather_data = {
City.NEW_YORK: cls(
city=City.get_display_name(City.NEW_YORK),
temperature_range="15-25°C",
conditions="Partly cloudy",
),
City.LONDON: cls(
city=City.get_display_name(City.LONDON),
temperature_range="10-15°C",
conditions="Rainy",
),
City.TOKYO: cls(
city=City.get_display_name(City.TOKYO),
temperature_range="20-30°C",
conditions="Sunny",
),
City.SYDNEY: cls(
city=City.get_display_name(City.SYDNEY),
temperature_range="18-23°C",
conditions="Clear",
),
}

return weather_data.get(
city,
cls(
city=(
City.get_display_name(city) if isinstance(city, City) else str(city)
),
temperature_range="15-25°C",
conditions="Unknown",
),
)


class WeatherRequest(BaseModel):
query: str
stream: bool = False
city: Optional[City] = None

class Config:
use_enum_values = True


class WeatherResponse(BaseModel):
response: str
weather_data: Optional[WeatherData] = None
trace_id: Optional[str] = None
Empty file added app/routers/__init__.py
Empty file.
Loading