Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
54e0c99
Support auto-pr-comment
imbajin Jun 11, 2025
85cd8c7
Merge remote-tracking branch 'upstream/main'
imbajin Jun 18, 2025
cb297dc
Merge remote-tracking branch 'upstream/main'
imbajin Jun 18, 2025
5962938
Merge remote-tracking branch 'upstream/main'
imbajin Jun 19, 2025
8280589
Merge remote-tracking branch 'upstream/main'
imbajin Jul 1, 2025
d6c472d
Merge remote-tracking branch 'upstream/main'
imbajin Jul 17, 2025
ea2efda
add basic
fantasy-lotus Jul 22, 2025
8c7fed1
Merge branch 'apache:main' into main
fantasy-lotus Jul 22, 2025
602c2ee
Merge branch 'apache:main' into main
fantasy-lotus Sep 9, 2025
08da949
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Sep 11, 2025
c82a4a2
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Oct 21, 2025
cfbcbd0
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Oct 23, 2025
d458f5a
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Oct 28, 2025
d174eee
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Nov 5, 2025
44035df
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Nov 5, 2025
b0d7ff5
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Nov 11, 2025
de99cae
Merge branch 'main' of https://github.com/apache/incubator-hugegraph-ai
actions-user Nov 15, 2025
dc863d8
feat ruff rule
fantasy-lotus Nov 24, 2025
f17161f
ruff auto lint
fantasy-lotus Nov 24, 2025
0f0f316
rm unused file
fantasy-lotus Nov 24, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@

class ExternalException(HTTPException):
def __init__(self):
super().__init__(
status_code=400, detail="Connect failed with error code -1, please check the input."
)
super().__init__(status_code=400, detail="Connect failed with error code -1, please check the input.")


class ConnectionFailedException(HTTPException):
Expand Down
60 changes: 15 additions & 45 deletions hugegraph-llm/src/hugegraph_llm/api/models/rag_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,13 @@ class RAGRequest(BaseModel):
raw_answer: bool = Query(False, description="Use LLM to generate answer directly")
vector_only: bool = Query(False, description="Use LLM to generate answer with vector")
graph_only: bool = Query(True, description="Use LLM to generate answer with graph RAG only")
graph_vector_answer: bool = Query(
False, description="Use LLM to generate answer with vector & GraphRAG"
)
graph_vector_answer: bool = Query(False, description="Use LLM to generate answer with vector & GraphRAG")
graph_ratio: float = Query(0.5, description="The ratio of GraphRAG ans & vector ans")
rerank_method: Literal["bleu", "reranker"] = Query(
"bleu", description="Method to rerank the results."
)
near_neighbor_first: bool = Query(
False, description="Prioritize near neighbors in the search results."
)
custom_priority_info: str = Query(
"", description="Custom information to prioritize certain results."
)
rerank_method: Literal["bleu", "reranker"] = Query("bleu", description="Method to rerank the results.")
near_neighbor_first: bool = Query(False, description="Prioritize near neighbors in the search results.")
custom_priority_info: str = Query("", description="Custom information to prioritize certain results.")
# Graph Configs
max_graph_items: int = Query(
30, description="Maximum number of items for GQL queries in graph."
)
max_graph_items: int = Query(30, description="Maximum number of items for GQL queries in graph.")
topk_return_results: int = Query(20, description="Number of sorted results to return finally.")
vector_dis_threshold: float = Query(
0.9,
Expand All @@ -64,14 +54,10 @@ class RAGRequest(BaseModel):
description="TopK results returned for each keyword \
extracted from the query, by default only the most similar one is returned.",
)
client_config: Optional[GraphConfigRequest] = Query(
None, description="hugegraph server config."
)
client_config: Optional[GraphConfigRequest] = Query(None, description="hugegraph server config.")

# Keep prompt params in the end
answer_prompt: Optional[str] = Query(
prompt.answer_prompt, description="Prompt to guide the answer generation."
)
answer_prompt: Optional[str] = Query(prompt.answer_prompt, description="Prompt to guide the answer generation.")
keywords_extract_prompt: Optional[str] = Query(
prompt.keywords_extract_prompt,
description="Prompt for extracting keywords from query.",
Expand All @@ -87,9 +73,7 @@ class RAGRequest(BaseModel):
class GraphRAGRequest(BaseModel):
query: str = Query(..., description="Query you want to ask")
# Graph Configs
max_graph_items: int = Query(
30, description="Maximum number of items for GQL queries in graph."
)
max_graph_items: int = Query(30, description="Maximum number of items for GQL queries in graph.")
topk_return_results: int = Query(20, description="Number of sorted results to return finally.")
vector_dis_threshold: float = Query(
0.9,
Expand All @@ -102,24 +86,16 @@ class GraphRAGRequest(BaseModel):
from the query, by default only the most similar one is returned.",
)

client_config: Optional[GraphConfigRequest] = Query(
None, description="hugegraph server config."
)
client_config: Optional[GraphConfigRequest] = Query(None, description="hugegraph server config.")
get_vertex_only: bool = Query(False, description="return only keywords & vertex (early stop).")

gremlin_tmpl_num: int = Query(
1,
description="Number of Gremlin templates to use. If num <=0 means template is not provided",
)
rerank_method: Literal["bleu", "reranker"] = Query(
"bleu", description="Method to rerank the results."
)
near_neighbor_first: bool = Query(
False, description="Prioritize near neighbors in the search results."
)
custom_priority_info: str = Query(
"", description="Custom information to prioritize certain results."
)
rerank_method: Literal["bleu", "reranker"] = Query("bleu", description="Method to rerank the results.")
near_neighbor_first: bool = Query(False, description="Prioritize near neighbors in the search results.")
custom_priority_info: str = Query("", description="Custom information to prioritize certain results.")
gremlin_prompt: Optional[str] = Query(
prompt.gremlin_generate_prompt,
description="Prompt for the Text2Gremlin query.",
Expand Down Expand Up @@ -163,16 +139,12 @@ class GremlinOutputType(str, Enum):

class GremlinGenerateRequest(BaseModel):
query: str
example_num: Optional[int] = Query(
0, description="Number of Gremlin templates to use.(0 means no templates)"
)
example_num: Optional[int] = Query(0, description="Number of Gremlin templates to use.(0 means no templates)")
gremlin_prompt: Optional[str] = Query(
prompt.gremlin_generate_prompt,
description="Prompt for the Text2Gremlin query.",
)
client_config: Optional[GraphConfigRequest] = Query(
None, description="hugegraph server config."
)
client_config: Optional[GraphConfigRequest] = Query(None, description="hugegraph server config.")
output_types: Optional[List[GremlinOutputType]] = Query(
default=[GremlinOutputType.TEMPLATE_GREMLIN],
description="""
Expand All @@ -189,7 +161,5 @@ def validate_prompt_placeholders(cls, v):
required_placeholders = ["{query}", "{schema}", "{example}", "{vertices}"]
missing = [p for p in required_placeholders if p not in v]
if missing:
raise ValueError(
f"Prompt template is missing required placeholders: {', '.join(missing)}"
)
raise ValueError(f"Prompt template is missing required placeholders: {', '.join(missing)}")
return v
31 changes: 8 additions & 23 deletions hugegraph-llm/src/hugegraph_llm/api/rag_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ def rag_answer_api(req: RAGRequest):
# Keep prompt params in the end
custom_related_information=req.custom_priority_info,
answer_prompt=req.answer_prompt or prompt.answer_prompt,
keywords_extract_prompt=req.keywords_extract_prompt
or prompt.keywords_extract_prompt,
keywords_extract_prompt=req.keywords_extract_prompt or prompt.keywords_extract_prompt,
gremlin_prompt=req.gremlin_prompt or prompt.gremlin_generate_prompt,
)
# TODO: we need more info in the response for users to understand the query logic
Expand Down Expand Up @@ -146,9 +145,7 @@ def graph_rag_recall_api(req: GraphRAGRequest):

except TypeError as e:
log.error("TypeError in graph_rag_recall_api: %s", e)
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)
) from e
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) from e
except Exception as e:
log.error("Unexpected error occurred: %s", e)
raise HTTPException(
Expand All @@ -159,9 +156,7 @@ def graph_rag_recall_api(req: GraphRAGRequest):
@router.post("/config/graph", status_code=status.HTTP_201_CREATED)
def graph_config_api(req: GraphConfigRequest):
# Accept status code
res = apply_graph_conf(
req.url, req.name, req.user, req.pwd, req.gs, origin_call="http"
)
res = apply_graph_conf(req.url, req.name, req.user, req.pwd, req.gs, origin_call="http")
return generate_response(RAGResponse(status_code=res, message="Missing Value"))

# TODO: restructure the implement of llm to three types, like "/config/chat_llm"
Expand All @@ -178,37 +173,27 @@ def llm_config_api(req: LLMConfigRequest):
origin_call="http",
)
else:
res = apply_llm_conf(
req.host, req.port, req.language_model, None, origin_call="http"
)
res = apply_llm_conf(req.host, req.port, req.language_model, None, origin_call="http")
return generate_response(RAGResponse(status_code=res, message="Missing Value"))

@router.post("/config/embedding", status_code=status.HTTP_201_CREATED)
def embedding_config_api(req: LLMConfigRequest):
llm_settings.embedding_type = req.llm_type

if req.llm_type == "openai":
res = apply_embedding_conf(
req.api_key, req.api_base, req.language_model, origin_call="http"
)
res = apply_embedding_conf(req.api_key, req.api_base, req.language_model, origin_call="http")
else:
res = apply_embedding_conf(
req.host, req.port, req.language_model, origin_call="http"
)
res = apply_embedding_conf(req.host, req.port, req.language_model, origin_call="http")
return generate_response(RAGResponse(status_code=res, message="Missing Value"))

@router.post("/config/rerank", status_code=status.HTTP_201_CREATED)
def rerank_config_api(req: RerankerConfigRequest):
llm_settings.reranker_type = req.reranker_type

if req.reranker_type == "cohere":
res = apply_reranker_conf(
req.api_key, req.reranker_model, req.cohere_base_url, origin_call="http"
)
res = apply_reranker_conf(req.api_key, req.reranker_model, req.cohere_base_url, origin_call="http")
elif req.reranker_type == "siliconflow":
res = apply_reranker_conf(
req.api_key, req.reranker_model, None, origin_call="http"
)
res = apply_reranker_conf(req.api_key, req.reranker_model, None, origin_call="http")
else:
res = status.HTTP_501_NOT_IMPLEMENTED
return generate_response(RAGResponse(status_code=res, message="Missing Value"))
Expand Down
4 changes: 1 addition & 3 deletions hugegraph-llm/src/hugegraph_llm/config/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate hugegraph-llm config file")
parser.add_argument(
"-U", "--update", default=True, action="store_true", help="Update the config file"
)
parser.add_argument("-U", "--update", default=True, action="store_true", help="Update the config file")
args = parser.parse_args()
if args.update:
huge_settings.generate_env()
Expand Down
4 changes: 1 addition & 3 deletions hugegraph-llm/src/hugegraph_llm/config/index_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ class IndexConfig(BaseConfig):

qdrant_host: Optional[str] = os.environ.get("QDRANT_HOST", None)
qdrant_port: int = int(os.environ.get("QDRANT_PORT", "6333"))
qdrant_api_key: Optional[str] = (
os.environ.get("QDRANT_API_KEY") if os.environ.get("QDRANT_API_KEY") else None
)
qdrant_api_key: Optional[str] = os.environ.get("QDRANT_API_KEY") if os.environ.get("QDRANT_API_KEY") else None

milvus_host: Optional[str] = os.environ.get("MILVUS_HOST", None)
milvus_port: int = int(os.environ.get("MILVUS_PORT", "19530"))
Expand Down
20 changes: 5 additions & 15 deletions hugegraph-llm/src/hugegraph_llm/config/llm_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,23 @@ class LLMConfig(BaseConfig):
hybrid_llm_weights: Optional[float] = 0.5
# TODO: divide RAG part if necessary
# 1. OpenAI settings
openai_chat_api_base: Optional[str] = os.environ.get(
"OPENAI_BASE_URL", "https://api.openai.com/v1"
)
openai_chat_api_base: Optional[str] = os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
openai_chat_api_key: Optional[str] = os.environ.get("OPENAI_API_KEY")
openai_chat_language_model: Optional[str] = "gpt-4.1-mini"
openai_extract_api_base: Optional[str] = os.environ.get(
"OPENAI_BASE_URL", "https://api.openai.com/v1"
)
openai_extract_api_base: Optional[str] = os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
openai_extract_api_key: Optional[str] = os.environ.get("OPENAI_API_KEY")
openai_extract_language_model: Optional[str] = "gpt-4.1-mini"
openai_text2gql_api_base: Optional[str] = os.environ.get(
"OPENAI_BASE_URL", "https://api.openai.com/v1"
)
openai_text2gql_api_base: Optional[str] = os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
openai_text2gql_api_key: Optional[str] = os.environ.get("OPENAI_API_KEY")
openai_text2gql_language_model: Optional[str] = "gpt-4.1-mini"
openai_embedding_api_base: Optional[str] = os.environ.get(
"OPENAI_EMBEDDING_BASE_URL", "https://api.openai.com/v1"
)
openai_embedding_api_base: Optional[str] = os.environ.get("OPENAI_EMBEDDING_BASE_URL", "https://api.openai.com/v1")
openai_embedding_api_key: Optional[str] = os.environ.get("OPENAI_EMBEDDING_API_KEY")
openai_embedding_model: Optional[str] = "text-embedding-3-small"
openai_chat_tokens: int = 8192
openai_extract_tokens: int = 256
openai_text2gql_tokens: int = 4096
# 2. Rerank settings
cohere_base_url: Optional[str] = os.environ.get(
"CO_API_URL", "https://api.cohere.com/v1/rerank"
)
cohere_base_url: Optional[str] = os.environ.get("CO_API_URL", "https://api.cohere.com/v1/rerank")
reranker_api_key: Optional[str] = None
reranker_model: Optional[str] = None
# 3. Ollama settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ def ensure_yaml_file_exists(self):
log.info("Prompt file '%s' doesn't exist, create it.", yaml_file_path)

def save_to_yaml(self):

def to_literal(val):
return LiteralStr(val) if isinstance(val, str) else val

Expand Down
4 changes: 1 addition & 3 deletions hugegraph-llm/src/hugegraph_llm/demo/rag_demo/admin_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ def create_admin_block():
)

# Error message box, initially hidden
error_message = gr.Textbox(
label="", visible=False, interactive=False, elem_classes="error-message"
)
error_message = gr.Textbox(label="", visible=False, interactive=False, elem_classes="error-message")

# Button to submit password
submit_button = gr.Button("Submit")
Expand Down
10 changes: 3 additions & 7 deletions hugegraph-llm/src/hugegraph_llm/demo/rag_demo/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,16 @@ def init_rag_ui() -> gr.Interface:
textbox_array_graph_config = create_configs_block()

with gr.Tab(label="1. Build RAG Index 💡"):
textbox_input_text, textbox_input_schema, textbox_info_extract_template = (
create_vector_graph_block()
)
textbox_input_text, textbox_input_schema, textbox_info_extract_template = create_vector_graph_block()
with gr.Tab(label="2. (Graph)RAG & User Functions 📖"):
(
textbox_inp,
textbox_answer_prompt_input,
textbox_keywords_extract_prompt_input,
textbox_custom_related_information
textbox_custom_related_information,
) = create_rag_block()
with gr.Tab(label="3. Text2gremlin ⚙️"):
textbox_gremlin_inp, textbox_gremlin_schema, textbox_gremlin_prompt = (
create_text2gremlin_block()
)
textbox_gremlin_inp, textbox_gremlin_schema, textbox_gremlin_prompt = create_text2gremlin_block()
with gr.Tab(label="4. Graph Tools 🚧"):
create_other_block()
with gr.Tab(label="5. Admin Tools 🛠"):
Expand Down
Loading
Loading