generate comprehensive response
Browse files
app.py
CHANGED
|
@@ -239,14 +239,23 @@ async def query_3D_object(
|
|
| 239 |
# raise gr.Error("Require at least 4 3D files to query by features")
|
| 240 |
if method == Query3DObjectMethod.HYBRID_SEARCH:
|
| 241 |
logger.info("Running query_3D_object_by_hybrid_search_method")
|
| 242 |
-
|
| 243 |
query, current_obj_path, embedding_dict, top_k
|
| 244 |
)
|
|
|
|
|
|
|
| 245 |
elif method == Query3DObjectMethod.SEMANTIC_SEARCH:
|
| 246 |
logger.info("Running query_3D_object_by_semantic_search_method")
|
| 247 |
-
|
| 248 |
query, current_obj_path, embedding_dict, top_k
|
| 249 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
|
| 251 |
|
| 252 |
def query_3D_object_by_semantic_search_method(
|
|
@@ -267,16 +276,21 @@ def query_3D_object_by_semantic_search_method(
|
|
| 267 |
scores = list(zip(filepaths, similarities))
|
| 268 |
scores.sort(key=lambda x: x[1], reverse=True)
|
| 269 |
|
| 270 |
-
if len(scores) < top_k:
|
| 271 |
-
|
| 272 |
|
| 273 |
top_files = [x[0] for x in scores[:top_k]]
|
| 274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
|
| 276 |
|
| 277 |
async def query_3D_object_by_hybrid_search_method(
|
| 278 |
query: str, current_obj_path: str, embedding_dict: dict, top_k: int = 4
|
| 279 |
-
) ->
|
| 280 |
# Keyword Search Agent
|
| 281 |
@function_tool
|
| 282 |
def query_3D_object_by_keyword_search(query: str, match_code: str, top_k: int = 4):
|
|
@@ -426,11 +440,19 @@ Combine the `match` function with `query_3D_object_by_keyword_search` to filter
|
|
| 426 |
)
|
| 427 |
return response
|
| 428 |
|
| 429 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
* Use `query_3D_object_by_semantic_search` for abstract or descriptive queries.
|
| 431 |
* Use `search_3D_similarity_factory` when the query mentions the object currently displayed on the screen and aims to find similar objects.
|
| 432 |
* Use **Keyword Search Agent** for precise metadata constraints or comparative/filtering information in the query.
|
| 433 |
-
Return only the final tuple of file paths and display names.
|
|
|
|
|
|
|
| 434 |
"""
|
| 435 |
|
| 436 |
HANDOFF_DESCRIPTION = """Handing off to Datum Agent: you can perform semantic search, keyword-based filtering, or visual similarity search.
|
|
@@ -444,6 +466,7 @@ If metadata filtering is required, delegate to the **Keyword Search Agent** by c
|
|
| 444 |
tools=[
|
| 445 |
query_3D_object_by_semantic_search,
|
| 446 |
search_3D_similarity_factory,
|
|
|
|
| 447 |
],
|
| 448 |
handoffs=[keyword_search_agent],
|
| 449 |
)
|
|
@@ -491,7 +514,7 @@ You need to find the most relevant 3D objects based on the query and return the
|
|
| 491 |
if len(result) < 2 * top_k:
|
| 492 |
n = len(result) // 2
|
| 493 |
result = result[:n] + [None] * (top_k - n) + result[n:] + [""] * (top_k - n)
|
| 494 |
-
return result
|
| 495 |
|
| 496 |
|
| 497 |
####################################################################################################################
|
|
@@ -877,6 +900,7 @@ with gr.Blocks() as demo:
|
|
| 877 |
with gr.Column():
|
| 878 |
query_input = gr.Textbox(placeholder="Which 3D CAD contains 2 holes?")
|
| 879 |
query_button = gr.Button("Query Search")
|
|
|
|
| 880 |
|
| 881 |
with gr.Row():
|
| 882 |
with gr.Row():
|
|
@@ -931,6 +955,7 @@ with gr.Blocks() as demo:
|
|
| 931 |
query_3D_object,
|
| 932 |
[query_input, model_render, embedding_store],
|
| 933 |
[
|
|
|
|
| 934 |
model_q_1,
|
| 935 |
model_q_2,
|
| 936 |
model_q_3,
|
|
|
|
| 239 |
# raise gr.Error("Require at least 4 3D files to query by features")
|
| 240 |
if method == Query3DObjectMethod.HYBRID_SEARCH:
|
| 241 |
logger.info("Running query_3D_object_by_hybrid_search_method")
|
| 242 |
+
result = await query_3D_object_by_hybrid_search_method(
|
| 243 |
query, current_obj_path, embedding_dict, top_k
|
| 244 |
)
|
| 245 |
+
response = result.get("response", "")
|
| 246 |
+
pairs = result.get("pairs", [])
|
| 247 |
elif method == Query3DObjectMethod.SEMANTIC_SEARCH:
|
| 248 |
logger.info("Running query_3D_object_by_semantic_search_method")
|
| 249 |
+
pairs = query_3D_object_by_semantic_search_method(
|
| 250 |
query, current_obj_path, embedding_dict, top_k
|
| 251 |
)
|
| 252 |
+
response = f"Here are the top-{top_k} results for your query: `{query}`"
|
| 253 |
+
else:
|
| 254 |
+
raise Exception(
|
| 255 |
+
f"Unsupported query method: {method}. Supported methods are: {list(Query3DObjectMethod)}"
|
| 256 |
+
)
|
| 257 |
+
assert len(pairs) == 2 * top_k
|
| 258 |
+
return [response] + pairs
|
| 259 |
|
| 260 |
|
| 261 |
def query_3D_object_by_semantic_search_method(
|
|
|
|
| 276 |
scores = list(zip(filepaths, similarities))
|
| 277 |
scores.sort(key=lambda x: x[1], reverse=True)
|
| 278 |
|
| 279 |
+
# if len(scores) < top_k:
|
| 280 |
+
# scores.extend([("", 0.0)] * (top_k - len(scores)))
|
| 281 |
|
| 282 |
top_files = [x[0] for x in scores[:top_k]]
|
| 283 |
+
result = top_files + [os.path.basename(x) for x in top_files]
|
| 284 |
+
# Fill None if lack of results
|
| 285 |
+
if len(result) < 2 * top_k:
|
| 286 |
+
n = len(result) // 2
|
| 287 |
+
result = result[:n] + [None] * (top_k - n) + result[n:] + [""] * (top_k - n)
|
| 288 |
+
return result
|
| 289 |
|
| 290 |
|
| 291 |
async def query_3D_object_by_hybrid_search_method(
|
| 292 |
query: str, current_obj_path: str, embedding_dict: dict, top_k: int = 4
|
| 293 |
+
) -> Dict:
|
| 294 |
# Keyword Search Agent
|
| 295 |
@function_tool
|
| 296 |
def query_3D_object_by_keyword_search(query: str, match_code: str, top_k: int = 4):
|
|
|
|
| 440 |
)
|
| 441 |
return response
|
| 442 |
|
| 443 |
+
@function_tool
|
| 444 |
+
def get_description_of_model_to_analysis(current_obj_path: str | None) -> str:
|
| 445 |
+
if current_obj_path is None:
|
| 446 |
+
raise gr.Error("Please select a file!")
|
| 447 |
+
return embedding_dict[current_obj_path]["description"]
|
| 448 |
+
|
| 449 |
+
DATUM_AGENT_INSTRUCTIONS = """You are the Datum Agent: you retrieve the top-K most relevant 3D objects using three strategies:
|
| 450 |
* Use `query_3D_object_by_semantic_search` for abstract or descriptive queries.
|
| 451 |
* Use `search_3D_similarity_factory` when the query mentions the object currently displayed on the screen and aims to find similar objects.
|
| 452 |
* Use **Keyword Search Agent** for precise metadata constraints or comparative/filtering information in the query.
|
| 453 |
+
Return only the final tuple of file paths and display names. If the response contains private paths which duplicated name, please ignore them!
|
| 454 |
+
Moreover, you can able to generate a comprehensive response when our users ask for a description of the current 3D object. In these cases, you are required to:
|
| 455 |
+
* Use `get_description_of_model_to_analysis` to retrieve the description of the current 3D object for analysis when receiving a user's query related to analysis or a description of the current view object.
|
| 456 |
"""
|
| 457 |
|
| 458 |
HANDOFF_DESCRIPTION = """Handing off to Datum Agent: you can perform semantic search, keyword-based filtering, or visual similarity search.
|
|
|
|
| 466 |
tools=[
|
| 467 |
query_3D_object_by_semantic_search,
|
| 468 |
search_3D_similarity_factory,
|
| 469 |
+
get_description_of_model_to_analysis,
|
| 470 |
],
|
| 471 |
handoffs=[keyword_search_agent],
|
| 472 |
)
|
|
|
|
| 514 |
if len(result) < 2 * top_k:
|
| 515 |
n = len(result) // 2
|
| 516 |
result = result[:n] + [None] * (top_k - n) + result[n:] + [""] * (top_k - n)
|
| 517 |
+
return {"pairs": result, "response": response.final_output}
|
| 518 |
|
| 519 |
|
| 520 |
####################################################################################################################
|
|
|
|
| 900 |
with gr.Column():
|
| 901 |
query_input = gr.Textbox(placeholder="Which 3D CAD contains 2 holes?")
|
| 902 |
query_button = gr.Button("Query Search")
|
| 903 |
+
response_box = gr.Textbox(placeholder="Thinking...", label="Response")
|
| 904 |
|
| 905 |
with gr.Row():
|
| 906 |
with gr.Row():
|
|
|
|
| 955 |
query_3D_object,
|
| 956 |
[query_input, model_render, embedding_store],
|
| 957 |
[
|
| 958 |
+
response_box,
|
| 959 |
model_q_1,
|
| 960 |
model_q_2,
|
| 961 |
model_q_3,
|