Skip to content
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
17 changes: 16 additions & 1 deletion aperag/api/components/schemas/model.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,19 @@ availableEmbeddingList:
type: array
items:
$ref: '#/availableEmbedding'


availableModel:
type: object
properties:
model_service_provider:
type: string
model_name:
type: string

availableModelList:
type: object
properties:
items:
type: array
items:
$ref: '#/availableModel'
2 changes: 2 additions & 0 deletions aperag/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ paths:
$ref: './paths/models.yaml#/modelServiceProvider'
/available_embeddings:
$ref: './paths/models.yaml#/availableEmbeddings'
/available_models:
$ref: './paths/models.yaml#/availableModels'


# config
Expand Down
18 changes: 18 additions & 0 deletions aperag/api/paths/models.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ availableEmbeddings:
schema:
$ref: '../components/schemas/common.yaml#/failResponse'

availableModels:
get:
summary: Get available models
description: Get available models
responses:
'200':
description: Available models
content:
application/json:
schema:
$ref: '../components/schemas/model.yaml#/availableModelList'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '../components/schemas/common.yaml#/failResponse'

modelServiceProvider:
put:
summary: Update model service provider
Expand Down
1 change: 0 additions & 1 deletion aperag/embed/base_embedding.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def wrapper(*args, **kwargs):

return wrapper


_dimension_cache: dict[tuple[str, str], int] = {}


Expand Down
3 changes: 0 additions & 3 deletions aperag/embed/embedding_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ def embed_query(self, text: str) -> List[float]:
reraise=True,
)
def _embed_batch(self, batch: Sequence[str]) -> List[List[float]]:
"""
单个 batch 的真正请求;加 tenacity 保证稳一点。
"""
response = litellm.embedding(
model=self.model,
api_base=self.api_base,
Expand Down
61 changes: 41 additions & 20 deletions aperag/graph/lightrag_holder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
from typing import Optional, List, Dict, Callable, Awaitable, Tuple, AsyncIterator, Any

import json
import numpy
from lightrag import LightRAG, QueryParam
from lightrag.kg.shared_storage import initialize_pipeline_status
Expand All @@ -10,6 +11,9 @@
from lightrag.base import DocStatus

from aperag.db.models import Collection
from aperag.db.ops import (
query_msp_dict,
)
from aperag.embed.base_embedding import get_collection_embedding_model
from aperag.utils.utils import generate_lightrag_namespace_prefix
from config.settings import (
Expand Down Expand Up @@ -72,24 +76,40 @@ async def adelete_by_doc_id(self, doc_id: str) -> None:


# ---------- Default llm_func & embed_impl ---------- #
async def _default_llm_func(
prompt: str,
system_prompt: Optional[str] = None,
history_messages: List = [],
**kwargs,
) -> str:
merged_kwargs = {
"api_key": LLM_API_KEY,
"base_url": LLM_BASE_URL,
"model": LLM_MODEL,
**kwargs,
}
return await openai_complete_if_cache(
prompt=prompt,
system_prompt=system_prompt,
history_messages=history_messages,
**merged_kwargs,
)
async def gen_lightrag_llm_func(collection: Collection) -> Callable[..., Awaitable[str]]:
config = json.loads(collection.config)
lightrag_backend = config.get("lightrag_model_service_provider", "")
lightrag_model_name = config.get("lightrag_model_name", "")
logging.info("gen_lightrag_llm_func %s %s", lightrag_backend, lightrag_model_name)

msp_dict = await query_msp_dict(collection.user)
if lightrag_backend in msp_dict:
msp = msp_dict[lightrag_backend]
lightrag_model_service_url = msp.base_url
lightrag_model_service_api_key = msp.api_key
logging.info("gen_lightrag_llm_func %s %s", lightrag_model_service_url, lightrag_model_service_api_key)

async def lightrag_llm_func(
prompt: str,
system_prompt: Optional[str] = None,
history_messages: List = [],
**kwargs,
) -> str:
merged_kwargs = {
"api_key": lightrag_model_service_api_key,
"base_url": lightrag_model_service_url,
"model": lightrag_model_name,
**kwargs,
}
return await openai_complete_if_cache(
prompt=prompt,
system_prompt=system_prompt,
history_messages=history_messages,
**merged_kwargs,
)
return lightrag_llm_func

return None

# Module-level cache
_lightrag_instances: Dict[str, LightRagHolder] = {}
Expand Down Expand Up @@ -145,9 +165,9 @@ async def lightrag_embed_func(texts: list[str]) -> numpy.ndarray:
return lightrag_embed_func, dim

async def get_lightrag_holder(
collection: Collection,
llm_func: Callable[..., Awaitable[str]] = _default_llm_func,
collection: Collection
) -> LightRagHolder:
# Fixme: if lightrag_model changes, we need to re-initialize the lightrag instance
namespace_prefix: str = generate_lightrag_namespace_prefix(collection.id)
if not namespace_prefix or not isinstance(namespace_prefix, str):
raise ValueError("A valid namespace_prefix string must be provided.")
Expand All @@ -162,6 +182,7 @@ async def get_lightrag_holder(
logger.info(f"Initializing LightRAG instance for namespace '{namespace_prefix}' (lazy loading)...")
try:
embed_func, dim = await gen_lightrag_embed_func(collection=collection)
llm_func = await gen_lightrag_llm_func(collection=collection)
client = await _create_and_initialize_lightrag(namespace_prefix, llm_func, embed_func, embed_dim=dim)
_lightrag_instances[namespace_prefix] = client
logger.info(f"LightRAG instance for namespace '{namespace_prefix}' initialized successfully.")
Expand Down
8 changes: 4 additions & 4 deletions aperag/tasks/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ def add_index_for_document(self, document_id):
}
document.relate_ids = json.dumps(relate_ids)

enable_light_rag = config.get("enable_light_rag", True)
if enable_light_rag:
enable_lightrag = config.get("enable_lightrag", True)
if enable_lightrag:
add_lightrag_index(content, document, local_doc)

except FeishuNoPermission:
Expand Down Expand Up @@ -355,8 +355,8 @@ def update_index_for_document(self, document_id):
document.relate_ids = json.dumps(relate_ids)
logger.info(f"update qdrant points: {document.relate_ids} for document {local_doc.path}")

enable_light_rag = config.get("enable_light_rag", True)
if enable_light_rag:
enable_lightrag = config.get("enable_lightrag", True)
if enable_lightrag:
add_lightrag_index(content, document, local_doc)

except FeishuNoPermission:
Expand Down
19 changes: 19 additions & 0 deletions aperag/views/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,25 @@ async def list_available_embeddings(request) -> view_models.AvailableEmbeddingLi
return success(view_models.AvailableEmbeddingList( items=response,))



@router.get("/available_models")
async def list_available_models(request) -> view_models.AvailableModelList:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use REST style API.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great suggestion, will be done in future PRs.

user = get_user(request)
supported_msp_dict = {supported_msp["name"]: supported_msp for supported_msp in settings.SUPPORTED_MODEL_SERVICE_PROVIDERS}
msp_list = await query_msp_list(user)
logger.info(msp_list)
response = []
for msp in msp_list:
if msp.name in supported_msp_dict:
supported_msp = supported_msp_dict[msp.name]
for model in supported_msp.get("models", []):
response.append(view_models.AvailableModel(
model_service_provider=msp.name,
model_name=model,
))
return success(view_models.AvailableModelList( items=response,))


def default_page(request, exception):
return render(request, '404.html')

Expand Down
11 changes: 10 additions & 1 deletion aperag/views/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# generated by datamodel-codegen:
# filename: openapi.merged.yaml
# timestamp: 2025-04-26T07:25:07+00:00
# timestamp: 2025-04-27T06:17:52+00:00

from __future__ import annotations

Expand Down Expand Up @@ -391,6 +391,15 @@ class AvailableEmbeddingList(BaseModel):
items: Optional[list[AvailableEmbedding]] = None


class AvailableModel(BaseModel):
model_service_provider: Optional[str] = None
model_name: Optional[str] = None


class AvailableModelList(BaseModel):
items: Optional[list[AvailableModel]] = None


class Auth0(BaseModel):
auth_domain: Optional[str] = None
auth_app_id: Optional[str] = None
Expand Down
37 changes: 36 additions & 1 deletion config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,18 @@
"text-embedding-3-small",
"text-embedding-3-large",
"text-embedding-ada-002",
],
"models": [
"gpt-3.5-turbo",
"gpt-4",
"gpt-4-turbo",
"gpt-4o-mini",
"gpt-4o",
"o1",
"o1-mini",
"o3",
"o3-mini",
"o4-mini",
]
},
{
Expand All @@ -269,13 +281,31 @@
"text-embedding-v1",
"text-embedding-v2",
"text-embedding-v3",
],
"models": [
"deepseek-r1",
"deepseek-v3",
"qwen-max",
"qwen-long",
"qwen-plus",
"qwen-plus-latest",
"qwen-turbo",
"qwq-32b",
"qwq-plus",
"qwq-plus-latest",
"qwen-vl-max",
"qwen-vl-plus"
]
},
{
"name": "deepseek",
"label": "DeepSeek",
"allow_custom_base_url": False,
"base_url": "https://api.deepseek.com/v1"
"base_url": "https://api.deepseek.com/v1",
"models": [
"deepseek-r1",
"deepseek-v3"
]
},
{
"name": "siliconflow",
Expand All @@ -286,6 +316,11 @@
"BAAI/bge-large-en-v1.5",
"BAAI/bge-large-zh-v1.5",
"BAAI/bge-m3",
],
"models": [
"Qwen/QwQ-32B",
"deepseek-ai/Deepseek-R1",
"deepseek-ai/Deepseek-V3",
]
},
]
Expand Down
6 changes: 1 addition & 5 deletions envs/env.template
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,7 @@ CHAT_CONSUMER_IMPLEMENTATION=document-qa
# RETRIEVE_MODE is one of: classic, graph, mix
RETRIEVE_MODE=classic

# --- LLM Settings ---
LIGHT_RAG_LLM_API_KEY=
LIGHT_RAG_LLM_BASE_URL=
LIGHT_RAG_LLM_MODEL=
# --- General Settings ---
# --- LIGHT RAG General Settings ---
LIGHT_RAG_WORKING_DIR=
LIGHT_RAG_ENABLE_LLM_CACHE=
LIGHT_RAG_MAX_PARALLEL_INSERT=
Expand Down
Loading