Duibonduil commited on
Commit
52f4d1c
·
verified ·
1 Parent(s): 7f4b706

Upload 13 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ AWorld-main/aworlddistributed/img.png filter=lfs diff=lfs merge=lfs -text
AWorld-main/aworlddistributed/.dockerignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .venv
2
+ .env
3
+ .git
4
+ .gitignore
5
+ .github
6
+ Dockerfile
7
+ examples
8
+ docs
9
+ *.md
10
+ dev.sh
11
+ dev-docker.sh
AWorld-main/aworlddistributed/.env_examples ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Development settings
2
+ LOG_FILE_PATH="aworldserver.log"
3
+
4
+ FILESYSTEM_SERVER_WORKDIR=""
5
+
6
+ ## LLM
7
+ LLM_PROVIDER=""
8
+ LLM_BASE_URL=""
9
+ LLM_API_KEY=""
10
+
11
+ ## TAVILY
12
+ TAVILY_API_KEY="xxx"
13
+
14
+
15
+ AUDIO_LLM_API_KEY=""
16
+ AUDIO_LLM_BASE_URL=""
17
+ AUDIO_LLM_MODEL_NAME=""
18
+
19
+ GOOGLE_API_KEY=""
20
+ GOOGLE_SEARCH_ENGINE_ID=""
21
+ GOOGLE_CSE_ID=""
22
+
23
+ E2B_API_KEY=""
24
+
25
+ APIFY_API_TOKEN=""
26
+
27
+ AMAP_API_KEY=""
28
+ START_TRACE_SERVER="true"
AWorld-main/aworlddistributed/.gitignore ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__
2
+ .env
3
+
4
+ /litellm
5
+
6
+ pipelines/*
7
+ !pipelines/.gitignore
8
+ .DS_Store
9
+ datasets/gaia_dataset/**
10
+ task_logs/**/*
11
+ task_logs/result/**/*
12
+
13
+ aworldspace/agents/**/*.json
14
+
15
+ .venv
16
+ venv/
AWorld-main/aworlddistributed/Dockerfile ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim-bookworm AS base
2
+
3
+
4
+ ## Basis ##
5
+ ENV ENV=prod \
6
+ PORT=9099
7
+
8
+ # Install GCC and build tools.
9
+ # These are kept in the final image to enable installing packages on the fly.
10
+ RUN apt-get update && \
11
+ apt-get install -y gcc build-essential curl git && \
12
+ apt-get clean && \
13
+ rm -rf /var/lib/apt/lists/*
14
+
15
+ RUN apt-get update && apt-get install -y wget unzip openssh-client procps nodejs npm
16
+
17
+ ARG PIP_OPTIONS='-i https://mirrors.aliyun.com/pypi/simple/'
18
+ ARG ENABLE_OSS_MOUNT=""
19
+
20
+ RUN pip install -U pip pysocks ${PIP_OPTIONS}
21
+
22
+ # Install Chrome Driver
23
+ RUN mkdir /app
24
+
25
+ RUN cd /app/ && \
26
+ wget https://storage.googleapis.com/chrome-for-testing-public/136.0.7103.92/linux64/chromedriver-linux64.zip && \
27
+ unzip chromedriver-linux64.zip && \
28
+ rm chromedriver-linux64.zip
29
+ ENV CHROME_DRIVER_PATH=/app/chromedriver-linux64/chromedriver
30
+
31
+
32
+ RUN if [ "$ENABLE_OSS_MOUNT" = "true" ]; then \
33
+ apt-get update && \
34
+ apt-get install -y gdebi-core mime-support && \
35
+ cd /tmp && \
36
+ wget https://gosspublic.alicdn.com/ossfs/ossfs_1.91.6_ubuntu22.04_amd64.deb && \
37
+ gdebi ossfs_1.91.6_ubuntu22.04_amd64.deb -n && \
38
+ rm ossfs_1.91.6_ubuntu22.04_amd64.deb && \
39
+ apt-get clean && \
40
+ rm -rf /var/lib/apt/lists/*; \
41
+ fi
42
+
43
+ FROM base as runner
44
+
45
+ WORKDIR /app
46
+
47
+ # Install Python dependencies
48
+ COPY ./requirements.txt .
49
+ RUN pip3 install uv ${PIP_OPTIONS}
50
+ RUN uv pip install --system -r requirements.txt --no-cache-dir ${PIP_OPTIONS}
51
+
52
+ # Copy the application code
53
+ RUN echo "start install aworld"
54
+ RUN mkdir -p /app/lib
55
+ RUN cd /app/lib && git clone https://github.com/inclusionAI/AWorld.git
56
+ RUN cd /app/lib/AWorld && git checkout framework_upgrade_aworldserver_gaia && pip install -r aworld/requirements.txt ${PIP_OPTIONS} && python setup.py install
57
+
58
+ RUN npx playwright install chrome --with-deps --no-shell
59
+
60
+ RUN cd /app
61
+
62
+
63
+
64
+ # Layer on for other components
65
+ FROM runner AS app
66
+
67
+ WORKDIR /app
68
+
69
+ COPY . .
70
+
71
+ # Expose the port
72
+ ENV HOST="0.0.0.0"
73
+ ENV PORT="9099"
74
+
75
+ # if we already installed the requirements on build, we can skip this step on run
76
+ ENTRYPOINT [ "bash", "start.sh" ]
AWorld-main/aworlddistributed/README.md ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AworldServer
2
+
3
+ AworldServer is an execution environment for the Aworld framework that integrates MCP LLM models. It supports distributed deployment and dynamic scaling.
4
+
5
+ ![img.png](img.png)
6
+
7
+ The system features:
8
+
9
+ - Distributed Architecture: Supports multi-server deployment with load balancing
10
+ - Dynamic Scaling: Ability to adjust server capacity based on demand
11
+ - LLM Integration: Built-in MCP LLM model support
12
+ - Asynchronous Processing: Uses asynchronous programming patterns for improved performance
13
+ - Containerized Deployment: Docker containerization support for easy environment management
14
+
15
+
16
+
17
+ ## 🚀 Quick Start
18
+
19
+ 1. Start services using Docker Compose:
20
+
21
+ ```sh
22
+ docker build --build-arg MINIMUM_BUILD=true -f Dockerfile --progress=plain -t aworldserver:main .
23
+
24
+ docker compose up -d
25
+ ```
26
+ 2. Configure the number of server instances:
27
+
28
+ You can modify the `docker-compose.yaml` file to adjust the number of server instances. The default configuration includes 3 instances:
29
+
30
+ 3. Usage Methods:
31
+
32
+ a. OpenWebUI Integration:
33
+ - Configure external link in OpenWebUI settings
34
+ - Add AworldServer endpoints to the configuration
35
+ - Set up API key authentication
36
+
37
+ b. Python Client Usage:
38
+ ```python
39
+ # Initialize AworldTaskClient with server endpoints
40
+ AWORLD_TASK_CLIENT = AworldTaskClient(
41
+ know_hosts=["localhost:9299", "localhost:9399", "localhost:9499"]
42
+ )
43
+
44
+ async def _run_gaia_task(gaia_question_id: str) -> None:
45
+ """Run a single Gaia task with the given question ID.
46
+
47
+ Args:
48
+ gaia_question_id: The ID of the question to process
49
+ """
50
+ global AWORLD_TASK_CLIENT
51
+ task_id = str(uuid.uuid4())
52
+
53
+ # Submit task to Aworld server
54
+ await AWORLD_TASK_CLIENT.submit_task(
55
+ AworldTask(
56
+ task_id=task_id,
57
+ agent_id="gaia_agent",
58
+ agent_input=gaia_question_id,
59
+ session_id="session_id",
60
+ user_id="SYSTEM"
61
+ )
62
+ )
63
+
64
+ # Get and print task result
65
+ task_result = await AWORLD_TASK_CLIENT.get_task_state(task_id=task_id)
66
+ print(task_result)
67
+
68
+ async def _batch_run_gaia_task(start_i: int, end_i: int) -> None:
69
+ """Run multiple Gaia tasks in parallel.
70
+
71
+ Args:
72
+ start_i: Starting question ID
73
+ end_i: Ending question ID
74
+ """
75
+ tasks = [
76
+ _run_gaia_task(str(i))
77
+ for i in range(start_i, end_i + 1)
78
+ ]
79
+ await asyncio.gather(*tasks)
80
+
81
+ if __name__ == '__main__':
82
+ # Run batch processing for questions 1-5
83
+ asyncio.run(_batch_run_gaia_task(1, 5))
84
+ ```
85
+ c. user curl
86
+ ```shell
87
+ curl http://localhost:9299/v1/chat/completions \
88
+ -H "Content-Type: application/json" \
89
+ -H "Authorization: Bearer 0p3n-w3bu!" \
90
+ -d '{
91
+ "model": "gaia_agent",
92
+ "messages": [
93
+ {
94
+ "role": "user",
95
+ "content": [
96
+ {
97
+ "type": "text",
98
+ "text": "5"
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ }'
104
+
105
+ ```
106
+
107
+
108
+ ## 🔑 Key Features
109
+
110
+ - **Distributed Task Processing System**
111
+ - Multi-server load balancing
112
+ - Round-robin task distribution
113
+ - Asynchronous task processing
114
+
115
+ - **Docker Containerization**
116
+ - Multi-instance deployment
117
+ - Environment variable configuration
118
+ - Auto-restart mechanism
119
+
120
+ - **API Services**
121
+ - FastAPI framework support
122
+ - RESTful API design
123
+ - Asynchronous request handling
124
+
125
+ - **Development Tools**
126
+ - Debug mode support
127
+ - Batch task processing
128
+ - Task state tracking
129
+
130
+ - **Security Features**
131
+ - API key authentication
132
+ - Session management
133
+ - User authentication
134
+
135
+
136
+
137
+ ## 📦 Installation and Setup
138
+
139
+ Get started with aworldserver in a few easy steps:
140
+
141
+ 1. **Ensure Python 3.11 is installed.**
142
+
143
+ 2. **Install the required dependencies:**
144
+
145
+ ```sh
146
+ pip install -r requirements-minimux.txt
147
+ ```
148
+
149
+ 3. **Start the aworld server:**
150
+
151
+ ```sh
152
+ sh ./start.sh
153
+ ```
154
+ ### Custom debug
155
+
156
+ please run `debug_run.py`
157
+
158
+ ##
AWorld-main/aworlddistributed/base.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+ from typing import Any
3
+ from typing import List, Optional
4
+ from datetime import datetime
5
+
6
+ from pydantic import BaseModel, ConfigDict
7
+ from pydantic import Field
8
+
9
+
10
+ class AworldTask(BaseModel):
11
+ task_id: str = Field(default=None, description="task id")
12
+ agent_id: str = Field(default=None, description="agent id")
13
+ agent_input: str = Field(default=None, description="agent input")
14
+ session_id: Optional[str] = Field(default=None, description="session id")
15
+ user_id: Optional[str] = Field(default=None, description="user id")
16
+ llm_provider: Optional[str] = Field(default=None, description="llm provider")
17
+ llm_model_name: Optional[str] = Field(default=None, description="llm model name")
18
+ llm_api_key: Optional[str] = Field(default=None, description="llm api key")
19
+ llm_base_url: Optional[str] = Field(default=None, description="llm base url")
20
+ llm_custom_input: Optional[str] = Field(default=None, description="custom_input")
21
+ task_system_prompt: Optional[str] = Field(default=None, description="task_system_prompt")
22
+ mcp_servers: Optional[list[str]] = Field(default=None, description="mcp_servers")
23
+ node_id: Optional[str] = Field(default=None, description="execute task node_id")
24
+ client_id: Optional[str] = Field(default=None, description="submit client ip")
25
+ status: Optional[str] = Field(default="INIT", description="submitted/running/execute_failed/execute_success")
26
+ history_messages: Optional[int] = Field(default=100, description="history_message")
27
+ max_steps: Optional[int] = Field(default=100, description="max_steps")
28
+ max_retries: Optional[int] = Field(default=5, description="max_retries use Exponential backoff with jitter")
29
+ ext_info: Optional[dict] = Field(default_factory=dict, description="custom")
30
+ created_at: Optional[datetime] = Field(default=None, description="created time")
31
+ updated_at: Optional[datetime] = Field(default=None, description="updated time")
32
+
33
+ def mark_running(self):
34
+ self.status = 'RUNNING'
35
+
36
+ def mark_failed(self):
37
+ self.status = 'FAILED'
38
+
39
+ def mark_success(self):
40
+ self.status = 'SUCCESS'
41
+
42
+ class AworldTaskResult(BaseModel):
43
+ task: AworldTask = Field(default=None, description="task")
44
+ server_host: Optional[str] = Field(default=None, description="aworld server id")
45
+ data: Any = Field(default=None, description="result data")
46
+
47
+ class AworldTaskForm(BaseModel):
48
+ batch_id: str = Field(default=str(uuid.uuid4()), description="batch_id")
49
+ task: Optional[AworldTask] = Field(default=None, description="task")
50
+ user_id: Optional[str] = Field(default=None, description="user id")
51
+ client_id: Optional[str] = Field(default=None, description="submit client ip")
52
+
53
+
54
+ class OpenAIChatMessage(BaseModel):
55
+ role: str
56
+ content: str | List
57
+
58
+ model_config = ConfigDict(extra="allow")
59
+
60
+
61
+ class OpenAIChatCompletionForm(BaseModel):
62
+ stream: bool = True
63
+ model: str
64
+ messages: List[OpenAIChatMessage]
65
+
66
+ model_config = ConfigDict(extra="allow")
67
+
68
+
69
+ class FilterForm(BaseModel):
70
+ body: dict
71
+ user: Optional[dict] = None
72
+ model_config = ConfigDict(extra="allow")
AWorld-main/aworlddistributed/config.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ from pathlib import Path
4
+
5
+ from aworld.utils.common import get_local_ip
6
+
7
+ ####################################
8
+ # Load .env file
9
+ ####################################
10
+
11
+ try:
12
+ from dotenv import load_dotenv, find_dotenv
13
+
14
+ load_dotenv(find_dotenv("./.env"))
15
+ except ImportError:
16
+ print("dotenv not installed, skipping...")
17
+
18
+ # Define log levels dictionary
19
+ LOG_LEVELS = {
20
+ 'DEBUG': logging.DEBUG,
21
+ 'INFO': logging.INFO,
22
+ 'WARNING': logging.WARNING,
23
+ 'ERROR': logging.ERROR,
24
+ 'CRITICAL': logging.CRITICAL
25
+ }
26
+ ROOT_DIR = Path(__file__).parent # the path containing this file
27
+ AGENTS_DIR = os.getenv("AGENTS_DIR", "./aworldspace/agents")
28
+ ROOT_LOG = os.path.join(os.getenv("LOG_DIR_PATH", "logs") , get_local_ip())
29
+ WORKSPACE_TYPE = os.environ.get("WORKSPACE_TYPE", "local")
30
+ WORKSPACE_PATH = os.environ.get("WORKSPACE_PATH", "./data/workspaces")
AWorld-main/aworlddistributed/debug_run.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import uvicorn
2
+ from dotenv import load_dotenv
3
+
4
+ if __name__ == "__main__":
5
+ load_dotenv()
6
+ import main
7
+ uvicorn.run(main.app, host="0.0.0.0", port=9999)
AWorld-main/aworlddistributed/docker-compose.yaml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ aworldserver-1:
3
+ image: aworldserver:main
4
+ volumes:
5
+ - ./.env:/app/.env
6
+ ports:
7
+ - "9299:9099"
8
+ restart: always
9
+ aworldserver-2:
10
+ image: aworldserver:main
11
+ volumes:
12
+ - ./.env:/app/.env
13
+ ports:
14
+ - "9399:9099"
15
+ restart: always
16
+ aworldserver-3:
17
+ image: aworldserver:main
18
+ volumes:
19
+ - ./.env:/app/.env
20
+ ports:
21
+ - "9499:9099"
22
+ restart: always
AWorld-main/aworlddistributed/img.png ADDED

Git LFS Details

  • SHA256: c5dca8761e334fc74b13de60ba1afb3ac6b69fb723294a2ac8e5574ac44caa7d
  • Pointer size: 131 Bytes
  • Size of remote file: 563 kB
AWorld-main/aworlddistributed/main.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ import time
4
+ from contextlib import asynccontextmanager
5
+ from logging.handlers import TimedRotatingFileHandler
6
+ import uvicorn
7
+
8
+ from fastapi import FastAPI, Request
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+
11
+ from aworld.cmd.web.routers import workspaces
12
+ from aworldspace.routes import tasks
13
+ from aworldspace.utils.job import generate_openai_chat_completion
14
+ from aworldspace.utils.loader import load_modules_from_directory, PIPELINE_MODULES, PIPELINES
15
+ from base import OpenAIChatCompletionForm
16
+ from config import AGENTS_DIR, LOG_LEVELS, ROOT_LOG
17
+
18
+ if not os.path.exists(AGENTS_DIR):
19
+ os.makedirs(AGENTS_DIR)
20
+
21
+ # Add GLOBAL_LOG_LEVEL for Pipeplines
22
+ log_level = os.getenv("GLOBAL_LOG_LEVEL", "INFO").upper()
23
+ logging.basicConfig(level=LOG_LEVELS[log_level])
24
+ def setup_logging():
25
+ logger = logging.getLogger()
26
+ logger.setLevel(logging.INFO)
27
+ log_dir = ROOT_LOG
28
+ if not os.path.exists(log_dir):
29
+ os.makedirs(log_dir)
30
+ log_path = os.path.join(log_dir, "aworldserver.log")
31
+ file_handler = TimedRotatingFileHandler(log_path, when='H', interval=1, backupCount=24)
32
+ file_handler.setLevel(logging.INFO)
33
+
34
+ formatter = logging.Formatter(
35
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
36
+ )
37
+ file_handler.setFormatter(formatter)
38
+
39
+ error_log_path = os.path.join(log_dir, "aworldserver_error.log")
40
+ error_file_handler = TimedRotatingFileHandler(error_log_path, when='D', interval=1, backupCount=24)
41
+ error_file_handler.setLevel(logging.WARNING)
42
+ error_file_handler.setFormatter(formatter)
43
+
44
+ logger.addHandler(file_handler)
45
+ logger.addHandler(error_file_handler)
46
+ setup_logging()
47
+
48
+
49
+ async def on_startup():
50
+ await load_modules_from_directory(AGENTS_DIR)
51
+ await tasks.task_manager.start_task_executor()
52
+
53
+ for module in PIPELINE_MODULES.values():
54
+ if hasattr(module, "on_startup"):
55
+ await module.on_startup()
56
+
57
+
58
+ async def on_shutdown():
59
+ for module in PIPELINE_MODULES.values():
60
+ if hasattr(module, "on_shutdown"):
61
+ await module.on_shutdown()
62
+
63
+
64
+ async def reload():
65
+ await on_shutdown()
66
+ # Clear existing pipelines
67
+ PIPELINES.clear()
68
+ PIPELINE_MODULES.clear()
69
+ # Load pipelines afresh
70
+ await on_startup()
71
+
72
+
73
+ @asynccontextmanager
74
+ async def lifespan(app: FastAPI):
75
+ await on_startup()
76
+ yield
77
+ await on_shutdown()
78
+
79
+
80
+ app = FastAPI(docs_url="/docs", redoc_url=None, lifespan=lifespan)
81
+
82
+
83
+ origins = ["*"]
84
+
85
+
86
+ app.add_middleware(
87
+ CORSMiddleware,
88
+ allow_origins=origins,
89
+ allow_credentials=True,
90
+ allow_methods=["*"],
91
+ allow_headers=["*"],
92
+ )
93
+ app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
94
+ app.include_router(workspaces.router, prefix="/api/v1/workspaces", tags=["workspace"])
95
+
96
+
97
+ @app.middleware("http")
98
+ async def check_url(request: Request, call_next):
99
+ start_time = int(time.time())
100
+ response = await call_next(request)
101
+ process_time = int(time.time()) - start_time
102
+ response.headers["X-Process-Time"] = str(process_time)
103
+
104
+ return response
105
+
106
+ @app.get("/v1")
107
+ @app.get("/")
108
+ async def get_status():
109
+ return {"status": True}
110
+
111
+
112
+ @app.post("/v1/chat/completions")
113
+ @app.post("/chat/completions")
114
+ async def chat_completion(form_data: OpenAIChatCompletionForm, request: Request
115
+ ):
116
+ # Extract headers into a dict
117
+ headers = request.headers
118
+ if headers.get("x-aworld-session-id"):
119
+ metadata = {
120
+ "user_id": headers.get("x-aworld-user-id"),
121
+ "chat_id": headers.get("x-aworld-session-id"),
122
+ "message_id": headers.get("x-aworld-message-id")
123
+ }
124
+
125
+ # Add metadata to form_data
126
+ form_data.metadata = metadata
127
+
128
+ return await generate_openai_chat_completion(form_data)
129
+
130
+ @app.get("/health")
131
+ async def healthcheck():
132
+ return {
133
+ "status": True
134
+ }
135
+
136
+
137
+ if __name__ == "__main__":
138
+ uvicorn.run(
139
+ "aworlddistributed.main:app",
140
+ host="0.0.0.0",
141
+ port=8088,
142
+ reload=True,
143
+ )
AWorld-main/aworlddistributed/requirements.txt ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ --index-url https://mirrors.aliyun.com/pypi/simple/
2
+
3
+ fastapi==0.111.0
4
+ uvicorn[standard]==0.23.1
5
+ pydantic==2.9.2
6
+ python-multipart==0.0.9
7
+ python-socketio
8
+ grpcio
9
+
10
+ passlib==1.7.4
11
+ passlib[bcrypt]
12
+ PyJWT[crypto]
13
+
14
+ requests==2.32.2
15
+ aiohttp==3.9.5
16
+ httpx
17
+
18
+ datasets==3.3.2
19
+ executing
20
+ flask
21
+ openpyxl
22
+ selenium==4.32.0
23
+ fitz==0.0.1.dev2
24
+ tabulate==0.9.0
25
+ frontend
26
+ tools
27
+ PyPDF2
28
+ html2text
29
+ xmltodict
30
+ docx2markdown
31
+ python-pptx
32
+ browser_use
33
+
34
+ oss2
35
+ prometheus_client~=0.21.1
36
+ opentelemetry-sdk~=1.32.1
37
+ opentelemetry-api~=1.32.1
38
+ opentelemetry-exporter-otlp~=1.32.1
39
+ opentelemetry-instrumentation-system-metrics~=0.53b1
40
+ e2b_code_interpreter
41
+
42
+ sqlalchemy~=2.0.40
43
+ psycopg2-binary==2.9.9
44
+ bcrypt==4.3.0
AWorld-main/aworlddistributed/start.sh ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ PORT="${PORT:-9099}"
3
+ HOST="${HOST:-0.0.0.0}"
4
+ # Default value for PIPELINES_DIR
5
+ PIPELINES_DIR=${PIPELINES_DIR:-./aworldspace/agents}
6
+
7
+ UVICORN_LOOP="${UVICORN_LOOP:-auto}"
8
+
9
+ # OSS mount configuration - read from environment variables
10
+ if [ -n "$OSS_BUCKET" ] && [ -n "$OSS_AK_ID" ] && [ -n "$OSS_AK_SECRET" ]; then
11
+ echo "Configuring OSS mount..."
12
+
13
+ # Create OSS credentials file
14
+ echo "${OSS_BUCKET}:${OSS_AK_ID}:${OSS_AK_SECRET}" >> /etc/passwd-ossfs
15
+ chmod 640 /etc/passwd-ossfs
16
+
17
+ # Create mount point directories if they don't exist
18
+ mkdir -p /app/logs
19
+ mkdir -p /app/trace_data
20
+ mkdir -p /app/aworldspace/datasets
21
+
22
+ # Mount OSS directories
23
+ echo "Mounting OSS directories..."
24
+ if [ -n "$OSS_REGION_URL" ] && [ -n "$OSS_BUCKET_URL" ]; then
25
+ # Use custom region and URL
26
+ ossfs ${OSS_BUCKET}:/aworld/logs /app/logs -odirect_read -ononempty -oregion=${OSS_REGION_URL} -ourl=${OSS_BUCKET_URL} &
27
+ ossfs ${OSS_BUCKET}:/aworld/trace_data /app/trace_data -odirect_read -ononempty -oregion=${OSS_REGION_URL} -ourl=${OSS_BUCKET_URL} &
28
+ ossfs ${OSS_BUCKET}:/aworld/datasets /app/aworldspace/datasets -odirect_read -ononempty -oregion=${OSS_REGION_URL} -ourl=${OSS_BUCKET_URL} &
29
+ else
30
+ # Use default configuration
31
+ ossfs ${OSS_BUCKET}:/aworld/logs /app/logs -odirect_read -ononempty &
32
+ ossfs ${OSS_BUCKET}:/aworld/trace_data /app/trace_data -odirect_read -ononempty &
33
+ ossfs ${OSS_BUCKET}:/aworld/datasets /app/aworldspace/datasets -odirect_read -ononempty &
34
+ fi
35
+
36
+ # Wait for mount to complete
37
+ sleep 2
38
+ echo "OSS mount configuration completed"
39
+ else
40
+ echo "OSS configuration incomplete, skipping OSS mount"
41
+ fi
42
+
43
+
44
+ uvicorn main:app --host "$HOST" --port "$PORT" --forwarded-allow-ips '*' --loop "$UVICORN_LOOP"
45
+