Skip to content

Commit 0ef4c32

Browse files
committed
Merge remote-tracking branch 'origin/develop' into pyh/feat_runtime_isolation_develop
2 parents 1c9a9e5 + 88ced66 commit 0ef4c32

File tree

21 files changed

+1216
-268
lines changed

21 files changed

+1216
-268
lines changed

backend/apps/vectordatabase_app.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from fastapi import APIRouter, Body, Depends, Header, HTTPException, Path, Query
66
from fastapi.responses import JSONResponse
77

8-
from consts.model import IndexingResponse
8+
from consts.model import HybridSearchRequest, IndexingResponse
99
from nexent.vector_database.base import VectorDatabaseCore
1010
from services.vectordatabase_service import (
1111
ElasticSearchService,
@@ -226,3 +226,32 @@ def get_index_chunks(
226226
f"Error getting chunks for index '{index_name}': {error_msg}")
227227
raise HTTPException(
228228
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=f"Error getting chunks: {error_msg}")
229+
230+
231+
@router.post("/search/hybrid")
232+
async def hybrid_search(
233+
payload: HybridSearchRequest,
234+
vdb_core: VectorDatabaseCore = Depends(get_vector_db_core),
235+
authorization: Optional[str] = Header(None),
236+
):
237+
"""Run a hybrid (accurate + semantic) search across indices."""
238+
try:
239+
_, tenant_id = get_current_user_id(authorization)
240+
result = ElasticSearchService.search_hybrid(
241+
index_names=payload.index_names,
242+
query=payload.query,
243+
tenant_id=tenant_id,
244+
top_k=payload.top_k,
245+
weight_accurate=payload.weight_accurate,
246+
vdb_core=vdb_core,
247+
)
248+
return JSONResponse(status_code=HTTPStatus.OK, content=result)
249+
except ValueError as exc:
250+
raise HTTPException(status_code=HTTPStatus.BAD_REQUEST,
251+
detail=str(exc))
252+
except Exception as exc:
253+
logger.error(f"Hybrid search failed: {exc}", exc_info=True)
254+
raise HTTPException(
255+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
256+
detail=f"Error executing hybrid search: {str(exc)}",
257+
)

backend/consts/model.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,18 @@ class IndexingResponse(BaseModel):
175175
total_submitted: int
176176

177177

178+
class HybridSearchRequest(BaseModel):
179+
"""Request payload for hybrid knowledge-base searches."""
180+
query: str = Field(..., min_length=1,
181+
description="Search query text")
182+
index_names: List[str] = Field(..., min_items=1,
183+
description="List of index names to search")
184+
top_k: int = Field(10, ge=1, le=100,
185+
description="Number of results to return")
186+
weight_accurate: float = Field(0.5, ge=0.0, le=1.0,
187+
description="Weight applied to accurate search scores")
188+
189+
178190
# Request models
179191
class ProcessParams(BaseModel):
180192
chunking_strategy: Optional[str] = "basic"

backend/services/vectordatabase_service.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,3 +996,66 @@ def get_index_chunks(
996996
error_msg = f"Error retrieving chunks from index {index_name}: {str(e)}"
997997
logger.error(error_msg)
998998
raise Exception(error_msg)
999+
1000+
@staticmethod
1001+
def search_hybrid(
1002+
*,
1003+
index_names: List[str],
1004+
query: str,
1005+
tenant_id: str,
1006+
top_k: int = 10,
1007+
weight_accurate: float = 0.5,
1008+
vdb_core: VectorDatabaseCore = Depends(get_vector_db_core),
1009+
):
1010+
"""
1011+
Execute a hybrid search that blends accurate and semantic scoring.
1012+
"""
1013+
try:
1014+
if not tenant_id:
1015+
raise ValueError("Tenant ID is required for hybrid search")
1016+
if not query or not query.strip():
1017+
raise ValueError("Query text is required for hybrid search")
1018+
if not index_names:
1019+
raise ValueError("At least one index name is required")
1020+
if top_k <= 0:
1021+
raise ValueError("top_k must be greater than 0")
1022+
if weight_accurate < 0 or weight_accurate > 1:
1023+
raise ValueError("weight_accurate must be between 0 and 1")
1024+
1025+
embedding_model = get_embedding_model(tenant_id)
1026+
if not embedding_model:
1027+
raise ValueError(
1028+
"No embedding model configured for the current tenant")
1029+
1030+
start_time = time.perf_counter()
1031+
raw_results = vdb_core.hybrid_search(
1032+
index_names=index_names,
1033+
query_text=query,
1034+
embedding_model=embedding_model,
1035+
top_k=top_k,
1036+
weight_accurate=weight_accurate,
1037+
)
1038+
elapsed_ms = int((time.perf_counter() - start_time) * 1000)
1039+
1040+
formatted_results = []
1041+
for item in raw_results:
1042+
document = dict(item.get("document", {}))
1043+
document["score"] = item.get("score")
1044+
document["index"] = item.get("index")
1045+
if "scores" in item:
1046+
document["score_details"] = item["scores"]
1047+
formatted_results.append(document)
1048+
1049+
return {
1050+
"results": formatted_results,
1051+
"total": len(formatted_results),
1052+
"query_time_ms": elapsed_ms,
1053+
}
1054+
except ValueError:
1055+
raise
1056+
except Exception as exc:
1057+
logger.error(
1058+
f"Hybrid search failed for indices {index_names}: {exc}",
1059+
exc_info=True,
1060+
)
1061+
raise Exception(f"Error executing hybrid search: {str(exc)}")

doc/docs/zh/opensource-memorial-wall.md

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,6 @@
1616
请保持消息的礼貌和尊重,符合我们的行为准则。
1717
-->
1818

19-
::: info happyzhang - 2025-11-13
20-
也许我们正见证着未来的“后起之秀”😀
21-
:::
22-
23-
::: info KevinLeeNJ - 2025-11-13
24-
来参加华为ICT大赛的,nexent很不错,希望后续能有更多功能!
25-
:::
26-
27-
::: info lzysleep - 2025-11-7
28-
非常不错的项目,很适合快速上手搭建自己的Agent,赞赞赞!
29-
:::
30-
31-
::: info fishcat - 2025-10-31
32-
很好的项目,希望蒸蒸日上
33-
:::
34-
35-
::: tip xiaomi250 - 2025-10-18
36-
打算冲一波 ICT 大赛!正好借着这个机会多捣鼓捣鼓,把我的技术再升个级,想想还挺有意思的~
37-
:::
38-
3919
::: tip aibito - 某创业公司后端开发 - 2025-05-18
4020
我们是一家只有 15 人的小公司,之前一直想做智能客服但技术门槛太高。发现 Nexent 后如获至宝!20+ 文件格式支持让我们轻松处理用户上传的各种文档,多模态对话功能完美解决了语音客服需求。最重要的是,我们的产品经理现在也能直接用自然语言调整智能体逻辑,开发效率提升了好几倍!
4121
:::
@@ -180,6 +160,10 @@ Nexent的自然语言生成Agent以及多智能体协同是我一直在研究的
180160
第一次接触智能体编排,是为了参加华为ICT大赛而了解 Nexent 的。 没想到入门比想象中容易,文档也写得很清晰。
181161
:::
182162

163+
::: tip xiaomi250 - 2025-10-18
164+
打算冲一波 ICT 大赛!正好借着这个机会多捣鼓捣鼓,把我的技术再升个级,想想还挺有意思的~
165+
:::
166+
183167
::: tip YuXiaoLoong - 2025-10-27
184168
Nexent是一个十分便利的开发平台,文档清晰,工具齐全,有幸能用上这么好用的平台,希望能在这个平台上学到更多技术和思想。
185169
:::
@@ -238,6 +222,8 @@ Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
238222

239223
::: info y-dq - 2025-10-28 
240224
想要自己尝试搭建智能体,感叹Nexent的功能如此强大!
225+
:::
226+
241227
::: tip cai7777 - 2025-10 23
242228
参加ICT大赛来了解 Nexent
243229
:::
@@ -314,6 +300,10 @@ Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
314300
感谢 Nexent 让我踏上了开源之旅!希望能参加ict大赛长长见识。项目不错,给个star~
315301
:::
316302

303+
::: info fishcat - 2025-10-31
304+
很好的项目,希望蒸蒸日上
305+
:::
306+
317307
:::info XxHosxX - 2025-11-5
318308
希望参与ICT大赛以及Nexent平台提升自己的能力:)
319309
:::
@@ -330,6 +320,10 @@ Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
330320
期待能使用Nexent成为智能体开发大佬
331321
:::
332322

323+
::: info lzysleep - 2025-11-7
324+
非常不错的项目,很适合快速上手搭建自己的Agent,赞赞赞!
325+
:::
326+
333327
::: info xiaochenIpter - 2025-11-08
334328
希望能参加ict大赛可以学习到更多知识,感谢 Nexent 让我踏上了开源之旅!平台开发智能体的能力十分强大,希望能够学习到更多东西!
335329
:::
@@ -398,6 +392,14 @@ Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
398392
我又来了,通过华为ICT了解到nexent,正在学习中...
399393
:::
400394

395+
::: info happyzhang - 2025-11-13
396+
也许我们正见证着未来的“后起之秀”😀
397+
:::
398+
399+
::: info KevinLeeNJ - 2025-11-13
400+
来参加华为ICT大赛的,nexent很不错,希望后续能有更多功能!
401+
:::
402+
401403
::: info user - 2025-11-14
402404
我要参加华为ICT
403405
:::
@@ -434,3 +436,66 @@ Nexent功能如此之强大,给我很多帮助,感谢开发者!厉害
434436
感谢 Nexent 让我踏上了开源之旅!给我一个机会制作智能体
435437
:::
436438

439+
::: info 开源小白 - 2025-11-19
440+
感谢 Nexent 让我踏上了开源之旅!这个项目的文档真的很棒,帮助我快速上手。
441+
:::
442+
443+
::: info chengyudan - 2025-10-20
444+
感谢 Nexent 让我踏上了开源之旅!
445+
:::
446+
447+
::: info user - 2025-11-20
448+
学习ai - agent非常好的项目,后面会持续输出贡献!
449+
:::
450+
451+
::: china-king-hs - 2025-11-20
452+
希望能正常使用nexent
453+
:::
454+
455+
::: info user - 2025-11-22
456+
感谢nexent这个开源项目
457+
:::
458+
459+
::: tip xiaofu-2025-11-23
460+
xiaofu到此一游,感谢 Nexent 让我踏上了开源之旅!
461+
:::
462+
463+
::: info DUTBenjamin - 2025-11-23
464+
来参加华为ICT大赛的,正好借着这个机会多捣鼓捣鼓,学到更多东西,加油!
465+
:::
466+
467+
::: dean-stock - 2025-11-23
468+
感谢nexent让我第一次接触到了智能体,让我从使用到创作智能体的转变。
469+
:::
470+
471+
::: user - 2025-11-23
472+
学习到ai了,很好用
473+
:::
474+
475+
::: info chao - 2025-11-23
476+
使用 Nexent 开发了项目,MCP 工具集成特别强大,节省了大量开发时间!
477+
:::
478+
479+
::: adasibi - 2025-11-23
480+
学习ai很好用,感谢 Nexent 让我踏上了开源之旅!
481+
:::
482+
483+
::: user - 2025-11-23
484+
Nexent越来越好!
485+
:::
486+
487+
::: info DUTBenjamin - 2025-11-23
488+
来参加华为ICT大赛的,正好借着这个机会学到更多东西,加油!
489+
:::
490+
491+
::: info aurorahashcat - 2025-11-23
492+
nexent看起来超棒的自动化智能体构建平台,祝越来越好😀
493+
:::
494+
495+
::: williamllk from SJTU - 2025-11-23
496+
感谢 Nexent 让我第一次制作智能体,尝试将AI4Science的理念付诸实践
497+
:::
498+
499+
::: tip lostlight530 - 2025-11-24
500+
通过 Nexent 实现了 Router-Worker 架构的完美落地。无论是构建高情商的拟人化伴侣,还是处理严苛的结构化数据约束,这套框架都游刃有余。多智能体编排体验极佳!
501+
:::

docker/docker-compose.prod.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ services:
250250
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
251251
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
252252
volumes:
253-
- ${ROOT_DIR}/minio/data:/data
253+
- ${ROOT_DIR}/minio/data:/etc/minio/data
254254
networks:
255255
- nexent
256256
restart: always

docker/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ services:
271271
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
272272
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
273273
volumes:
274-
- ${ROOT_DIR}/minio/data:/data
274+
- ${ROOT_DIR}/minio/data:/etc/minio/data
275275
networks:
276276
- nexent
277277
restart: always

0 commit comments

Comments
 (0)