limcheekin commited on
Commit
b92d070
1 Parent(s): 990a127

feat: first import

Browse files
Dockerfile ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM debian:bullseye-slim AS build-image
2
+
3
+ ARG MODEL="BAAI/bge-large-en"
4
+ ENV MODEL=${MODEL}
5
+
6
+ COPY ./download.sh ./
7
+
8
+ # Install build dependencies
9
+ RUN apt-get update && \
10
+ apt-get install -y git-lfs
11
+
12
+ RUN chmod +x *.sh && \
13
+ ./download.sh && \
14
+ rm *.sh
15
+
16
+ # Stage 3 - final runtime image
17
+ # Grab a fresh copy of the Python image
18
+ FROM python:3.10-slim
19
+
20
+ ARG MODEL="BAAI/bge-large-en"
21
+ ENV MODEL=${MODEL}
22
+ ENV NORMALIZE_EMBEDDINGS=1
23
+
24
+ RUN mkdir -p ${MODEL} && mkdir -p open/text/embeddings
25
+ COPY --from=build-image ${MODEL} ${MODEL}
26
+ COPY open/text/embeddings ./open/text/embeddings
27
+ COPY server-requirements.txt ./
28
+ RUN pip install --no-cache-dir -r server-requirements.txt
29
+
30
+ COPY ./start_server.sh ./
31
+ COPY ./index.html ./
32
+
33
+ # Make the server start script executable
34
+ RUN chmod +x ./start_server.sh
35
+
36
+ # Set environment variable for the host
37
+ ENV HOST=0.0.0.0
38
+ ENV PORT=7860
39
+
40
+ # Expose a port for the server
41
+ EXPOSE ${PORT}
42
+
43
+ # Run the server start script
44
+ CMD ["/bin/sh", "./start_server.sh"]
README.md CHANGED
@@ -1,10 +1,19 @@
1
  ---
2
- title: Bge Large En
3
  emoji: 👁
4
  colorFrom: gray
5
  colorTo: pink
6
  sdk: docker
 
 
 
 
 
 
 
7
  pinned: false
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: BAAI/bge-large-en OpenAI API-Compatible Endpoint
3
  emoji: 👁
4
  colorFrom: gray
5
  colorTo: pink
6
  sdk: docker
7
+ models:
8
+ - BAAI/bge-large-en
9
+ tags:
10
+ - inference api
11
+ - openai-api compatible
12
+ - open-text-embeddings
13
+ - bge-large-en
14
  pinned: false
15
  ---
16
 
17
+ # BAAI/bge-large-en OpenAI API-Compatible Endpoint
18
+
19
+ Please refer to the [main screen](https://huggingface.co/spaces/limcheekin/bge-large-en) for more information.
download.sh ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ mkdir -p $MODEL
2
+ git lfs install --skip-smudge
3
+ git clone https://huggingface.co/$MODEL $MODEL
4
+ cd $MODEL
5
+ git lfs pull
6
+ git lfs install --force
7
+ rm -rf .git
8
+ pwd
9
+ ls -l
index.html ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>BAAI/bge-large-en OpenAI API-Compatible Endpoint</title>
5
+ </head>
6
+ <body>
7
+ <h1>BAAI/bge-large-en OpenAI API-Compatible Endpoint</h1>
8
+ <p>
9
+ With the utilization of the
10
+ <a href="https://github.com/limcheekin/open-text-embeddings"
11
+ >open-text-embeddings</a
12
+ >
13
+ package, we are excited to introduce the text embeddings model hosted in
14
+ the Hugging Face Docker Spaces, made accessible through an
15
+ OpenAI-compatible API. This space includes comprehensive API documentation
16
+ to facilitate seamless integration.
17
+ </p>
18
+ <ul>
19
+ <li>
20
+ The API endpoint:
21
+ <a href="https://limcheekin-bge-large-en.hf.space/v1"
22
+ >https://limcheekin-bge-large-en.hf.space/v1</a
23
+ >
24
+ </li>
25
+ <li>
26
+ The API doc:
27
+ <a href="https://limcheekin-bge-large-en.hf.space/docs"
28
+ >https://limcheekin-bge-large-en.hf.space/docs</a
29
+ >
30
+ </li>
31
+ </ul>
32
+ <p>
33
+ If you find this resource valuable, your support in the form of starring
34
+ the space would be greatly appreciated. Your engagement plays a vital role
35
+ in furthering the application for a community GPU grant, ultimately
36
+ enhancing the capabilities and accessibility of this space.
37
+ </p>
38
+ </body>
39
+ </html>
open/__init__.py ADDED
File without changes
open/text/embeddings/server/__main__.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FastAPI server for open-text-embeddings.
2
+
3
+ To run this example:
4
+
5
+ ```bash
6
+ pip install -r --no-cache-dir server-requirements.txt
7
+ ```
8
+
9
+ Then run:
10
+ ```
11
+ MODEL=intfloat/e5-large-v2 python -m open.text.embeddings.server
12
+ ```
13
+
14
+ Then visit http://localhost:8000/docs to see the interactive API docs.
15
+
16
+ """
17
+ import uvicorn
18
+ from fastapi.responses import HTMLResponse
19
+ from open.text.embeddings.server.app import create_app
20
+ import os
21
+
22
+ app = create_app()
23
+
24
+ # Read the content of index.html once and store it in memory
25
+ with open("index.html", "r") as f:
26
+ content = f.read()
27
+
28
+
29
+ @app.get("/", response_class=HTMLResponse)
30
+ async def read_items():
31
+ return content
32
+
33
+ if __name__ == "__main__":
34
+ uvicorn.run(app,
35
+ host=os.environ["HOST"],
36
+ port=int(os.environ["PORT"])
37
+ )
open/text/embeddings/server/app.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from typing import List, Optional, Union
3
+ from starlette.concurrency import run_in_threadpool
4
+ from fastapi import FastAPI, APIRouter
5
+ from fastapi.middleware.cors import CORSMiddleware
6
+ from pydantic import BaseModel, Field
7
+ from langchain.embeddings import HuggingFaceEmbeddings
8
+ from langchain.embeddings import HuggingFaceInstructEmbeddings
9
+ from langchain.embeddings import HuggingFaceBgeEmbeddings
10
+ import os
11
+
12
+ router = APIRouter()
13
+
14
+ DEFAULT_MODEL_NAME = "intfloat/e5-large-v2"
15
+ E5_EMBED_INSTRUCTION = "passage: "
16
+ E5_QUERY_INSTRUCTION = "query: "
17
+ BGE_EN_QUERY_INSTRUCTION = "Represent this sentence for searching relevant passages: "
18
+ BGE_ZH_QUERY_INSTRUCTION = "为这个句子生成表示以用于检索相关文章:"
19
+
20
+
21
+ def create_app():
22
+ app = FastAPI(
23
+ title="Open Text Embeddings API",
24
+ version="0.0.2",
25
+ )
26
+ app.add_middleware(
27
+ CORSMiddleware,
28
+ allow_origins=["*"],
29
+ allow_credentials=True,
30
+ allow_methods=["*"],
31
+ allow_headers=["*"],
32
+ )
33
+ app.include_router(router)
34
+
35
+ return app
36
+
37
+
38
+ class CreateEmbeddingRequest(BaseModel):
39
+ model: Optional[str] = Field(
40
+ description="The model to use for generating embeddings.")
41
+ input: Union[str, List[str]] = Field(description="The input to embed.")
42
+ user: Optional[str]
43
+
44
+ class Config:
45
+ schema_extra = {
46
+ "example": {
47
+ "input": "The food was delicious and the waiter...",
48
+ }
49
+ }
50
+
51
+
52
+ class Embedding(BaseModel):
53
+ embedding: List[float]
54
+
55
+
56
+ class CreateEmbeddingResponse(BaseModel):
57
+ data: List[Embedding]
58
+
59
+
60
+ embeddings = None
61
+
62
+
63
+ def _create_embedding(
64
+ request: CreateEmbeddingRequest
65
+ ):
66
+ global embeddings
67
+
68
+ if embeddings is None:
69
+ if request.model and request.model != "text-embedding-ada-002":
70
+ model_name = request.model
71
+ else:
72
+ model_name = os.environ["MODEL"]
73
+ print("Loading model:", model_name)
74
+ encode_kwargs = {
75
+ "normalize_embeddings": bool(os.environ.get("NORMALIZE_EMBEDDINGS", ""))
76
+ }
77
+ print("encode_kwargs", encode_kwargs)
78
+ if "e5" in model_name:
79
+ embeddings = HuggingFaceInstructEmbeddings(model_name=model_name,
80
+ embed_instruction=E5_EMBED_INSTRUCTION,
81
+ query_instruction=E5_QUERY_INSTRUCTION,
82
+ encode_kwargs=encode_kwargs)
83
+ elif model_name.startswith("BAAI/bge-") and model_name.endswith("-en"):
84
+ embeddings = HuggingFaceBgeEmbeddings(model_name=model_name,
85
+ query_instruction=BGE_EN_QUERY_INSTRUCTION,
86
+ encode_kwargs=encode_kwargs)
87
+ elif model_name.startswith("BAAI/bge-") and model_name.endswith("-zh"):
88
+ embeddings = HuggingFaceBgeEmbeddings(model_name=model_name,
89
+ query_instruction=BGE_ZH_QUERY_INSTRUCTION,
90
+ encode_kwargs=encode_kwargs)
91
+ else:
92
+ embeddings = HuggingFaceEmbeddings(
93
+ model_name=model_name, encode_kwargs=encode_kwargs)
94
+
95
+ if isinstance(request.input, str):
96
+ return CreateEmbeddingResponse(data=[Embedding(embedding=embeddings.embed_query(request.input))])
97
+ else:
98
+ data = [Embedding(embedding=embedding)
99
+ for embedding in embeddings.embed_documents(request.input)]
100
+ return CreateEmbeddingResponse(data=data)
101
+
102
+
103
+ @router.post(
104
+ "/v1/embeddings",
105
+ response_model=CreateEmbeddingResponse,
106
+ )
107
+ async def create_embedding(
108
+ request: CreateEmbeddingRequest
109
+ ):
110
+ return _create_embedding(request)
111
+ # throw TypeError: 'CreateEmbeddingResponse' object is not callable?
112
+ # return await run_in_threadpool(
113
+ # _create_embedding(request)
114
+ # )
server-requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi
2
+ sse-starlette
3
+ sentence_transformers
4
+ langchain
5
+ uvicorn
start_server.sh ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ python -B -m open.text.embeddings.server