Skip to content

Single paper recomendation

This tool is used to return recommendations for a single paper.

SinglePaperRecInput

Bases: BaseModel

Input schema for single paper recommendation tool.

Source code in aiagents4pharma/talk2competitors/tools/s2/single_paper_rec.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class SinglePaperRecInput(BaseModel):
    """Input schema for single paper recommendation tool."""

    paper_id: str = Field(
        description="Semantic Scholar Paper ID to get recommendations for (40-character string)"
    )
    limit: int = Field(
        default=2,
        description="Maximum number of recommendations to return",
        ge=1,
        le=500,
    )
    year: Optional[str] = Field(
        default=None,
        description="Year range in format: YYYY for specific year, "
        "YYYY- for papers after year, -YYYY for papers before year, or YYYY:YYYY for range",
    )
    tool_call_id: Annotated[str, InjectedToolCallId]
    model_config = {"arbitrary_types_allowed": True}

get_single_paper_recommendations(paper_id, tool_call_id, limit=2, year=None)

Get paper recommendations based on a single paper.

Parameters:

Name Type Description Default
paper_id str

The Semantic Scholar Paper ID to get recommendations for.

required
tool_call_id Annotated[str, InjectedToolCallId]

The tool call ID.

required
limit int

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

2
year str

Year range for papers.

None
Supports formats like "2024-", "-2024", "2024

2025". Defaults to None.

required

Returns:

Type Description
Dict[str, Any]

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

Source code in aiagents4pharma/talk2competitors/tools/s2/single_paper_rec.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
@tool(args_schema=SinglePaperRecInput)
def get_single_paper_recommendations(
    paper_id: str,
    tool_call_id: Annotated[str, InjectedToolCallId],
    limit: int = 2,
    year: Optional[str] = None,
) -> Dict[str, Any]:
    """
    Get paper recommendations based on a single paper.

    Args:
        paper_id (str): The Semantic Scholar Paper ID to get recommendations for.
        tool_call_id (Annotated[str, InjectedToolCallId]): The tool call ID.
        limit (int, optional): The maximum number of recommendations to return. Defaults to 2.
        year (str, optional): Year range for papers.
        Supports formats like "2024-", "-2024", "2024:2025". Defaults to None.

    Returns:
        Dict[str, Any]: The recommendations and related information.
    """
    logger.info("Starting single paper recommendations search.")

    endpoint = (
        f"https://api.semanticscholar.org/recommendations/v1/papers/forpaper/{paper_id}"
    )
    params = {
        "limit": min(limit, 500),  # Max 500 per API docs
        "fields": "paperId,title,abstract,year,authors,citationCount,url",
        "from": "all-cs",  # Using all-cs pool as specified in docs
    }

    # Add year parameter if provided
    if year:
        params["year"] = year

    response = requests.get(endpoint, params=params, timeout=10)
    data = response.json()
    papers = data.get("data", [])
    response = requests.get(endpoint, params=params, timeout=10)
    # print(f"API Response Status: {response.status_code}")
    logging.info(
        "API Response Status for recommendations of paper %s: %s",
        paper_id,
        response.status_code,
    )
    # print(f"Request params: {params}")
    logging.info("Request params: %s", params)

    data = response.json()
    recommendations = data.get("recommendedPapers", [])

    # Extract paper ID and title from recommendations
    filtered_papers = {
        paper["paperId"]: {
            "Title": paper.get("title", "N/A"),
            "Abstract": paper.get("abstract", "N/A"),
            "Year": paper.get("year", "N/A"),
            "Citation Count": paper.get("citationCount", "N/A"),
            "URL": paper.get("url", "N/A"),
            # "Publication Type": paper.get("publicationTypes", ["N/A"])[0]
            # if paper.get("publicationTypes")
            # else "N/A",
            # "Open Access PDF": paper.get("openAccessPdf", {}).get("url", "N/A")
            # if paper.get("openAccessPdf") is not None
            # else "N/A",
        }
        for paper in recommendations
        if paper.get("title") and paper.get("authors")
    }

    # Create a DataFrame for pretty printing
    df = pd.DataFrame(filtered_papers)

    # Format papers for state update
    papers = [
        f"Paper ID: {paper_id}\n"
        f"Title: {paper_data['Title']}\n"
        f"Abstract: {paper_data['Abstract']}\n"
        f"Year: {paper_data['Year']}\n"
        f"Citations: {paper_data['Citation Count']}\n"
        f"URL: {paper_data['URL']}\n"
        # f"Publication Type: {paper_data['Publication Type']}\n"
        # f"Open Access PDF: {paper_data['Open Access PDF']}"
        for paper_id, paper_data in filtered_papers.items()
    ]

    # Convert DataFrame to markdown table
    markdown_table = df.to_markdown(tablefmt="grid")
    logging.info("Search results: %s", papers)

    return Command(
        update={
            "papers": filtered_papers,  # Now sending the dictionary directly
            "messages": [
                ToolMessage(content=markdown_table, tool_call_id=tool_call_id)
            ],
        }
    )