|
22 | 22 | store_transcript, |
23 | 23 | get_rag_toolgroups, |
24 | 24 | evaluate_model_hints, |
| 25 | + _process_knowledge_search_content, |
25 | 26 | ) |
26 | 27 |
|
27 | 28 | from models.requests import QueryRequest, Attachment |
@@ -1583,3 +1584,141 @@ def test_evaluate_model_hints( |
1583 | 1584 |
|
1584 | 1585 | assert provider_id == expected_provider |
1585 | 1586 | assert model_id == expected_model |
| 1587 | + |
| 1588 | + |
| 1589 | +def test_process_knowledge_search_content_with_valid_metadata(mocker): |
| 1590 | + """Test _process_knowledge_search_content with valid metadata.""" |
| 1591 | + # Mock tool response with valid metadata |
| 1592 | + text_content_item = mocker.Mock() |
| 1593 | + text_content_item.text = """Result 1 |
| 1594 | +Content: Test content |
| 1595 | +Metadata: {'docs_url': 'https://example.com/doc1', 'title': 'Test Doc', 'document_id': 'doc-1'} |
| 1596 | +""" |
| 1597 | + |
| 1598 | + tool_response = mocker.Mock() |
| 1599 | + tool_response.content = [text_content_item] |
| 1600 | + |
| 1601 | + metadata_map = {} |
| 1602 | + |
| 1603 | + _process_knowledge_search_content(tool_response, metadata_map) |
| 1604 | + |
| 1605 | + # Verify metadata was correctly parsed and added |
| 1606 | + assert "doc-1" in metadata_map |
| 1607 | + assert metadata_map["doc-1"]["docs_url"] == "https://example.com/doc1" |
| 1608 | + assert metadata_map["doc-1"]["title"] == "Test Doc" |
| 1609 | + assert metadata_map["doc-1"]["document_id"] == "doc-1" |
| 1610 | + |
| 1611 | + |
| 1612 | +def test_process_knowledge_search_content_with_invalid_metadata_syntax_error(mocker): |
| 1613 | + """Test _process_knowledge_search_content handles SyntaxError from invalid metadata.""" |
| 1614 | + mock_logger = mocker.patch("app.endpoints.query.logger") |
| 1615 | + |
| 1616 | + # Mock tool response with invalid metadata (invalid Python syntax) |
| 1617 | + text_content_item = mocker.Mock() |
| 1618 | + text_content_item.text = """Result 1 |
| 1619 | +Content: Test content |
| 1620 | +Metadata: {'docs_url': 'https://example.com/doc1' 'title': 'Test Doc', 'document_id': 'doc-1'} |
| 1621 | +""" # Missing comma between 'doc1' and 'title' - will cause SyntaxError |
| 1622 | + |
| 1623 | + tool_response = mocker.Mock() |
| 1624 | + tool_response.content = [text_content_item] |
| 1625 | + |
| 1626 | + metadata_map = {} |
| 1627 | + |
| 1628 | + _process_knowledge_search_content(tool_response, metadata_map) |
| 1629 | + |
| 1630 | + # Verify metadata_map remains empty due to exception |
| 1631 | + assert len(metadata_map) == 0 |
| 1632 | + |
| 1633 | + # Verify debug logging was called |
| 1634 | + mock_logger.debug.assert_called_once() |
| 1635 | + args = mock_logger.debug.call_args[0] |
| 1636 | + assert "An exception was thrown in processing" in args[0] |
| 1637 | + |
| 1638 | + |
| 1639 | +def test_process_knowledge_search_content_with_invalid_metadata_value_error(mocker): |
| 1640 | + """Test _process_knowledge_search_content handles ValueError from invalid metadata.""" |
| 1641 | + mock_logger = mocker.patch("app.endpoints.query.logger") |
| 1642 | + |
| 1643 | + # Mock tool response with invalid metadata containing complex expressions |
| 1644 | + text_content_item = mocker.Mock() |
| 1645 | + text_content_item.text = """Result 1 |
| 1646 | +Content: Test content |
| 1647 | +Metadata: {func_call(): 'value', 'title': 'Test Doc', 'document_id': 'doc-1'} |
| 1648 | +""" # Function call in dict - will cause ValueError since it's not a literal |
| 1649 | + |
| 1650 | + tool_response = mocker.Mock() |
| 1651 | + tool_response.content = [text_content_item] |
| 1652 | + |
| 1653 | + metadata_map = {} |
| 1654 | + |
| 1655 | + _process_knowledge_search_content(tool_response, metadata_map) |
| 1656 | + |
| 1657 | + # Verify metadata_map remains empty due to exception |
| 1658 | + assert len(metadata_map) == 0 |
| 1659 | + |
| 1660 | + # Verify debug logging was called |
| 1661 | + mock_logger.debug.assert_called_once() |
| 1662 | + args = mock_logger.debug.call_args[0] |
| 1663 | + assert "An exception was thrown in processing" in args[0] |
| 1664 | + |
| 1665 | + |
| 1666 | +def test_process_knowledge_search_content_with_non_dict_metadata(mocker): |
| 1667 | + """Test _process_knowledge_search_content handles non-dict metadata gracefully.""" |
| 1668 | + mock_logger = mocker.patch("app.endpoints.query.logger") |
| 1669 | + |
| 1670 | + # Mock tool response with metadata that's not a dict |
| 1671 | + text_content_item = mocker.Mock() |
| 1672 | + text_content_item.text = """Result 1 |
| 1673 | +Content: Test content |
| 1674 | +Metadata: "just a string" |
| 1675 | +""" |
| 1676 | + |
| 1677 | + tool_response = mocker.Mock() |
| 1678 | + tool_response.content = [text_content_item] |
| 1679 | + |
| 1680 | + metadata_map = {} |
| 1681 | + |
| 1682 | + _process_knowledge_search_content(tool_response, metadata_map) |
| 1683 | + |
| 1684 | + # Verify metadata_map remains empty (no document_id in string) |
| 1685 | + assert len(metadata_map) == 0 |
| 1686 | + |
| 1687 | + # No exception should be logged since string is valid literal |
| 1688 | + mock_logger.debug.assert_not_called() |
| 1689 | + |
| 1690 | + |
| 1691 | +def test_process_knowledge_search_content_with_metadata_missing_document_id(mocker): |
| 1692 | + """Test _process_knowledge_search_content skips metadata without document_id.""" |
| 1693 | + # Mock tool response with valid metadata but missing document_id |
| 1694 | + text_content_item = mocker.Mock() |
| 1695 | + text_content_item.text = """Result 1 |
| 1696 | +Content: Test content |
| 1697 | +Metadata: {'docs_url': 'https://example.com/doc1', 'title': 'Test Doc'} |
| 1698 | +""" # No document_id field |
| 1699 | + |
| 1700 | + tool_response = mocker.Mock() |
| 1701 | + tool_response.content = [text_content_item] |
| 1702 | + |
| 1703 | + metadata_map = {} |
| 1704 | + |
| 1705 | + _process_knowledge_search_content(tool_response, metadata_map) |
| 1706 | + |
| 1707 | + # Verify metadata_map remains empty since document_id is missing |
| 1708 | + assert len(metadata_map) == 0 |
| 1709 | + |
| 1710 | + |
| 1711 | +def test_process_knowledge_search_content_with_no_text_attribute(mocker): |
| 1712 | + """Test _process_knowledge_search_content skips content items without text attribute.""" |
| 1713 | + # Mock tool response with content item that has no text attribute |
| 1714 | + text_content_item = mocker.Mock(spec=[]) # spec=[] means no attributes |
| 1715 | + |
| 1716 | + tool_response = mocker.Mock() |
| 1717 | + tool_response.content = [text_content_item] |
| 1718 | + |
| 1719 | + metadata_map = {} |
| 1720 | + |
| 1721 | + _process_knowledge_search_content(tool_response, metadata_map) |
| 1722 | + |
| 1723 | + # Verify metadata_map remains empty since text attribute is missing |
| 1724 | + assert len(metadata_map) == 0 |
0 commit comments