Skip to content

Zotero Read

This tool is used to search for papers in Zotero library.

ZoteroSearchInput

Bases: BaseModel

Input schema for the Zotero search tool.

Source code in aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class ZoteroSearchInput(BaseModel):
    """Input schema for the Zotero search tool."""

    query: str = Field(
        description="Search query string to find papers in Zotero library."
    )
    only_articles: bool = Field(
        default=True,
        description="Whether to only search for journal articles/" "conference papers.",
    )
    limit: int = Field(
        default=2, description="Maximum number of results to return", ge=1, le=100
    )
    tool_call_id: Annotated[str, InjectedToolCallId]

zotero_search_tool(query, only_articles, tool_call_id, limit=2)

Use this tool to search and retrieve papers from Zotero library.

Parameters:

Name Type Description Default
query str

The search query string to find papers.

required
tool_call_id Annotated[str, InjectedToolCallId]

The tool call ID.

required
limit int

The maximum number of results to return. Defaults to 2.

2

Returns:

Type Description
Command[Any]

Dict[str, Any]: The search results and related information.

Source code in aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
@tool(args_schema=ZoteroSearchInput, parse_docstring=True)
def zotero_search_tool(
    query: str,
    only_articles: bool,
    tool_call_id: Annotated[str, InjectedToolCallId],
    limit: int = 2,
) -> Command[Any]:
    """
    Use this tool to search and retrieve papers from Zotero library.

    Args:
        query (str): The search query string to find papers.
        tool_call_id (Annotated[str, InjectedToolCallId]): The tool call ID.
        limit (int, optional): The maximum number of results to return. Defaults to 2.

    Returns:
        Dict[str, Any]: The search results and related information.
    """
    logger.info(
        "Searching Zotero for query: '%s' (only_articles: %s, limit: %d)",
        query,
        only_articles,
        limit,
    )

    # Initialize Zotero client
    zot = zotero.Zotero(cfg.user_id, cfg.library_type, cfg.api_key)

    # Get items matching the query
    items = zot.items(q=query, limit=min(limit, cfg.zotero.max_limit))
    logger.info("Received %d items from Zotero", len(items))

    # Define filter criteria
    filter_item_types = cfg.zotero.filter_item_types if only_articles else []

    # Filter and format papers
    filtered_papers = {}

    for item in items:
        if not isinstance(item, dict):
            continue

        data = item.get("data")
        if not isinstance(data, dict):
            continue

        item_type = data.get("itemType")
        if only_articles and (
            not item_type
            or not isinstance(item_type, str)
            or item_type not in filter_item_types
        ):
            continue

        key = data.get("key")
        if not key:
            continue

        filtered_papers[key] = {
            "Title": data.get("title", "N/A"),
            "Abstract": data.get("abstractNote", "N/A"),
            "Date": data.get("date", "N/A"),
            "URL": data.get("url", "N/A"),
            "Type": item_type if isinstance(item_type, str) else "N/A",
        }

    if not filtered_papers:
        logger.warning("No matching papers found for query: '%s'", query)

    logger.info("Filtered %d items", len(filtered_papers))

    # Prepare content with top 3 paper titles and types
    top_papers = list(filtered_papers.values())[:2]
    top_papers_info = "\n".join(
        [
            f"{i+1}. {paper['Title']} ({paper['Type']})"
            for i, paper in enumerate(top_papers)
        ]
    )

    content = "Retrieval was successful. Papers are attached as an artifact."
    content += " And here is a summary of the retrieval results:\n"
    content += f"Number of papers found: {len(filtered_papers)}\n"
    content += f"Query: {query}\n"
    content += "Top papers:\n" + top_papers_info

    return Command(
        update={
            "zotero_read": filtered_papers,
            "last_displayed_papers": "zotero_read",
            "messages": [
                ToolMessage(
                    content=content,
                    tool_call_id=tool_call_id,
                    artifact=filtered_papers,
                )
            ],
        }
    )