-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
113 changed files
with
6,919 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
__pycache__/ | ||
.idea/ | ||
venv/ | ||
.venv | ||
.env | ||
volumes/ | ||
logs | ||
.vscode | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# app | ||
APP_NAME=open-assistant-api | ||
APP_DEBUG=True | ||
APP_ENV=local | ||
APP_SERVER_HOST=0.0.0.0 | ||
APP_SERVER_PORT=8086 | ||
APP_SERVER_WORKERS=1 | ||
APP_API_PREFIX=/api | ||
|
||
LOG_LEVEL=DEBUG | ||
|
||
# database | ||
DB_HOST=127.0.0.1 | ||
DB_PORT=3306 | ||
DB_DATABASE=open_assistant | ||
DB_USER=root | ||
DB_PASSWORD=123456 | ||
DB_POOL_SIZE=1 | ||
|
||
# redis | ||
REDIS_HOST=localhost | ||
REDIS_PORT=6379 | ||
REDIS_DB=0 | ||
REDIS_PASSWORD=123456 | ||
|
||
# file service | ||
FILE_SERVICE_MODULE=app.services.file.impl.oss_file.OSSFileService | ||
|
||
# s3 storage | ||
S3_ENDPOINT=http://minio:9000 | ||
S3_BUCKET_NAME=oas | ||
S3_ACCESS_KEY=minioadmin | ||
S3_SECRET_KEY=minioadmin | ||
S3_REGION=us-east-1 | ||
|
||
# celery | ||
CELERY_BROKER_URL=redis://:[email protected]:6379/1 | ||
|
||
# llm | ||
OPENAI_API_BASE= | ||
OPENAI_API_KEY= | ||
LLM_MAX_STEP=25 | ||
|
||
# tool | ||
TOOL_WORKER_NUM=10 | ||
TOOL_WORKER_EXECUTION_TIMEOUT=180 | ||
|
||
# web search tool | ||
BING_SEARCH_URL=https://api.bing.microsoft.com/v7.0/search | ||
BING_SUBSCRIPTION_KEY=xxxx | ||
WEB_SEARCH_NUM_RESULTS=5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
__pycache__/ | ||
.idea/ | ||
venv/ | ||
.venv | ||
.env | ||
volumes/ | ||
logs | ||
.vscode | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
FROM python:3.10-slim AS base | ||
|
||
LABEL maintainer="[email protected]" | ||
|
||
COPY docker/sources.list /etc/apt/sources.list | ||
RUN apt-get update \ | ||
&& apt-get install -y --no-install-recommends bash curl wget vim libmagic-dev \ | ||
&& apt-get autoremove \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ --no-cache-dir poetry \ | ||
&& poetry config virtualenvs.create false | ||
|
||
COPY poetry.lock /env/poetry.lock | ||
COPY pyproject.toml /env/pyproject.toml | ||
|
||
RUN cd /env && poetry install --no-dev | ||
|
||
EXPOSE 8086 | ||
|
||
WORKDIR /app | ||
|
||
COPY . /app | ||
|
||
COPY docker/entrypoint.sh /entrypoint.sh | ||
RUN chmod +x /entrypoint.sh | ||
|
||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.PHONY: all format lint | ||
|
||
all: help | ||
|
||
help: | ||
@echo "make" | ||
|
||
@echo " format" | ||
@echo " Apply black formatting to code." | ||
@echo " lint" | ||
@echo " Lint code with ruff, and check if black formatter should be applied." | ||
|
||
format: | ||
poetry run black . | ||
poetry run ruff . --fix | ||
|
||
lint: | ||
poetry run black . --check | ||
poetry run ruff . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,110 @@ | ||
# open-assistant-api | ||
<div align="center"> | ||
|
||
# Open Assistant Api | ||
|
||
_✨ 开箱即用的 AI 智能助手 API ✨_ | ||
|
||
</div> | ||
|
||
## 简介 | ||
|
||
Open Assistant API 是一个开源自托管的 AI 智能助手 API,兼容 OpenAI 官方接口, | ||
可以直接使用 OpenAI 官方的 [Client](https://github.com/openai/openai-python) 构建 LLM 应用。 | ||
|
||
支持 [One API](https://github.com/songquanpeng/one-api) 可以用其接入更多商业和私有模型。 | ||
|
||
## 使用 | ||
|
||
以下是使用了 OpenAI 官方的 Python `openai` 库的使用示例: | ||
|
||
```python | ||
import openai | ||
|
||
client = openai.OpenAI( | ||
base_url="http://127.0.0.1:8086/api/v1", | ||
api_key="xxx" | ||
) | ||
|
||
assistant = client.beta.assistants.create( | ||
name="demo", | ||
instructions="You are a helpful assistant.", | ||
model="gpt-4-1106-preview" | ||
) | ||
``` | ||
|
||
## 为什么选择 Open Assistant API | ||
|
||
| 功能 | Open Assistant API | OpenAI Assistant API | | ||
|------------------|--------------------|----------------------| | ||
| 生态策略 | 开源 | 闭源 | | ||
| RAG 引擎 | 简单实现 | 支持 | | ||
| 联网搜索 | 支持 | 不支持 | | ||
| 自定义 Functions | 支持 | 支持 | | ||
| 内置 Tool | 支持扩展 | 不支持扩展 | | ||
| Code Interpreter | 待开发 | 支持 | | ||
| LLM 支持 | 支持更多的 LLM | 仅 GPT | | ||
| 本地部署 | 支持 | 不支持 | | ||
|
||
- **LLM 支持**: 相较于 OpenAI 官方版本,可以通过接入 One API 来支持更多的模型。 | ||
- **Tool**: 目前支持联网搜索;可以较容易扩展更多的 Tool。 | ||
- **RAG 引擎**: 目前支持的文件类型有 txt、pdf、html、markdown。我们提供了一个初步的实现。 | ||
- **生态策略**: 开源,你可以将服务部署在本地,可以对已有功能进行扩展。 | ||
|
||
## 快速上手 | ||
|
||
启动 Open Assistant API 最简单方法是运行 docker-compose.yml 文件。 运行之前确保机器上安装了 Docker 和 Docker Compose。 | ||
|
||
### 配置 | ||
|
||
进入项目根目录,打开 `docker-compose.yml`,填写 openai api_key 和 bing search key (非必填)。 | ||
|
||
```sh | ||
# openai api_key | ||
OPENAI_API_KEY=<openai_api_key> | ||
|
||
# bing search key (非必填) | ||
BING_SUBSCRIPTION_KEY=<bing_subscription_key> | ||
``` | ||
|
||
### 运行 | ||
|
||
#### 使用 Docker Compose 运行: | ||
|
||
```sh | ||
docker compose up -d | ||
``` | ||
|
||
### 访问 API | ||
|
||
Api Base URL: http://127.0.0.1:8086/api/v1 | ||
|
||
接口文档地址: http://127.0.0.1:8086/docs | ||
|
||
### 完整使用示例 | ||
|
||
此示例中使用 OpenAI 官方的 client 库创建并运行了一个 AI 助手,包含了 web_search 和 retrieval 两个内置 tool 和一个自定义 function。 | ||
运行之前需要运行 `pip install openai` 安装 Python `openai` 库。 | ||
|
||
```sh | ||
# !pip install openai | ||
python tests/e2e/index.py | ||
``` | ||
|
||
## 特别感谢 | ||
|
||
我们主要参考和依赖了以下项目: | ||
|
||
- [OpenOpenAI](https://github.com/transitive-bullshit/OpenOpenAI): Node 实现的 Assistant API | ||
- [One API](https://github.com/songquanpeng/one-api): 多模型管理工具 | ||
- [OpenAI-Python](https://github.com/openai/openai-python): OpenAI Python Client | ||
- [OpenAI API](https://github.com/openai/openai-openapi): OpenAI 接口定义 | ||
- [LangChain](https://github.com/langchain-ai/langchain): LLM 应用开发库 | ||
- [OpenGPTs](https://github.com/langchain-ai/opengpts): LangChain GPTs | ||
|
||
## 参与贡献 | ||
|
||
请阅读我们的[贡献文档](./docs/CONTRIBUTING.md),了解如何参与贡献。 | ||
|
||
## 开源协议 | ||
|
||
本仓库遵循 MIT 开源协议。有关详细信息,请参阅 [LICENSE](./LICENSE) 文件。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# A generic, single database configuration. | ||
|
||
[alembic] | ||
# path to migration scripts | ||
script_location = migrations | ||
|
||
# template used to generate migration files | ||
# file_template = %%(rev)s_%%(slug)s | ||
file_template = %%(year)d-%%(month).2d-%%(day).2d-%%(hour).2d-%%(minute).2d_%%(rev)s | ||
|
||
# timezone to use when rendering the date | ||
# within the migration file as well as the filename. | ||
# string value is passed to dateutil.tz.gettz() | ||
# leave blank for localtime | ||
# timezone = | ||
|
||
# max length of characters to apply to the | ||
# "slug" field | ||
#truncate_slug_length = 40 | ||
|
||
# set to 'true' to run the environment during | ||
# the 'revision' command, regardless of autogenerate | ||
# revision_environment = false | ||
|
||
# set to 'true' to allow .pyc and .pyo files without | ||
# a source .py file to be detected as revisions in the | ||
# versions/ directory | ||
# sourceless = false | ||
|
||
# version location specification; this defaults | ||
# to alembic/versions. When using multiple version | ||
# directories, initial revisions must be specified with --version-path | ||
# version_locations = %(here)s/bar %(here)s/bat alembic/versions | ||
|
||
# the output encoding used when revision files | ||
# are written from script.py.mako | ||
# output_encoding = utf-8 | ||
|
||
# Logging configuration | ||
[loggers] | ||
keys = root,sqlalchemy,alembic | ||
|
||
[handlers] | ||
keys = console | ||
|
||
[formatters] | ||
keys = generic | ||
|
||
[logger_root] | ||
level = WARN | ||
handlers = console | ||
qualname = | ||
|
||
[logger_sqlalchemy] | ||
level = WARN | ||
handlers = | ||
qualname = sqlalchemy.engine | ||
|
||
[logger_alembic] | ||
level = INFO | ||
handlers = | ||
qualname = alembic | ||
|
||
[handler_console] | ||
class = StreamHandler | ||
args = (sys.stderr,) | ||
level = NOTSET | ||
formatter = generic | ||
|
||
[formatter_generic] | ||
format = %(levelname)-5.5s [%(name)s] %(message)s | ||
datefmt = %H:%M:%S |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from sqlmodel import Session | ||
|
||
from app.providers import database | ||
|
||
|
||
def get_session(): | ||
with Session(database.engine) as session: | ||
yield session |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from fastapi import APIRouter | ||
from app.api.v1 import assistant, assistant_file, thread, message, files, runs | ||
|
||
api_router = APIRouter(prefix="/v1") | ||
|
||
api_router.include_router(assistant.router, prefix="/assistants", tags=["assistants"]) | ||
api_router.include_router(assistant_file.router, prefix="/assistants", tags=["assistants"]) | ||
api_router.include_router(thread.router, prefix="/threads", tags=["threads"]) | ||
api_router.include_router(message.router, prefix="/threads", tags=["messages"]) | ||
api_router.include_router(runs.router, prefix="/threads", tags=["runs"]) | ||
api_router.include_router(files.router, prefix="/files", tags=["files"]) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from fastapi import APIRouter, Depends | ||
from sqlmodel import Session, select | ||
|
||
from app.api.deps import get_session | ||
from app.models.assistant import Assistant, AssistantUpdate | ||
from app.libs.paginate import cursor_page, CommonPage | ||
from app.schemas.common import DeleteResponse | ||
from app.services.assistant.assistant import AssistantService | ||
|
||
router = APIRouter() | ||
|
||
|
||
@router.get("", response_model=CommonPage[Assistant]) | ||
def list_assistants(*, session: Session = Depends(get_session)): | ||
""" | ||
Returns a list of assistants. | ||
""" | ||
return cursor_page(select(Assistant), session) | ||
|
||
|
||
@router.post("", response_model=Assistant) | ||
def create_assistant(*, session: Session = Depends(get_session), body: Assistant) -> Assistant: | ||
""" | ||
Create an assistant with a model and instructions. | ||
""" | ||
return AssistantService.create_assistant(session=session, body=body) | ||
|
||
|
||
@router.get("/{assistant_id}", response_model=Assistant) | ||
def get_assistant(*, session: Session = Depends(get_session), assistant_id: str) -> Assistant: | ||
""" | ||
Retrieves an assistant. | ||
""" | ||
return AssistantService.get_assistant(session=session, assistant_id=assistant_id) | ||
|
||
|
||
@router.post("/{assistant_id}", response_model=Assistant) | ||
def modify_assistant(*, session: Session = Depends(get_session), assistant_id: str, body: AssistantUpdate) -> Assistant: | ||
""" | ||
Modifies an assistant. | ||
""" | ||
return AssistantService.modify_assistant(session=session, assistant_id=assistant_id, body=body) | ||
|
||
|
||
@router.delete("/{assistant_id}", response_model=DeleteResponse) | ||
def delete_assistant(*, session: Session = Depends(get_session), assistant_id: str) -> DeleteResponse: | ||
""" | ||
Delete an assistant. | ||
""" | ||
return AssistantService.delete_assistant(session=session, assistant_id=assistant_id) |
Oops, something went wrong.