Skip to content

ai4curation/agent-tutorial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

Monarch Agent Tutorial

We will be walking through the process of creating an ontology agent. The goal is to empower you as a Python developer to turbo-charge your applications with AI.

If you are curious about AI but feel intimidated by the confusing range of tools and acronyms out there, this tutorial is meant for you!

The intended audience is the OBO and Monarch communities, but all are welcome!

Recording

This tutorial was a part of the Monarch OBO Academy training.

See the recording on YouTube

Pre-requisites

  1. Some knowledge of Python
  2. uv installed locally
  3. An IDE or text editor (I will use cursor in the walk-through, but any should work)
  4. An OpenAI API key, with OPENAI_API_KEY set
    • All developers in Monarch should already have a key
    • LBNL developers can use cborg, see instructions below
    • It should be possible to modify examples to use a different model, but we won't covert this in the interests of time
    • Otherwise sign up to get an OpenAI key

Additionally, some knowledge of ontologies like UBERON and the capabilities of the OAK will help.

Initializing the project

Install uv

Follow the instructions here: https://docs.astral.sh/uv/getting-started/installation/

On a mac:

curl -LsSf https://astral.sh/uv/install.sh | sh

Create the repo

uv init --package agent-tutorial

Add dependencies

cd agent-tutorial

(or open the terminal in your IDE)

uv add pydantic-ai

PART 1: Create a basic agent

We will be using pydantic-ai.

img

There are many other agent frameworks available: langgraph, crew-ai, smolagents. Each has its own strengths and weaknesses and it is often a matter of preference.

Create hello_world.py

Create this in src/agent_tutorial/hello_world.py

Copy the example from here:

https://ai.pydantic.dev/#hello-world-example

Adapt it to use openai:gpt-4o (unless you have a )

from pydantic_ai import Agent

agent = Agent(  
    'openai:gpt-4o',
    system_prompt='Be concise, reply with one sentence.',  
)

result = agent.run_sync('Where does "hello world" come from?')  
print(result.data)
"""
The first known use of "hello, world" was in a 1974 textbook about the C programming language.
"""

Run it

uv run src/agent_tutorial/hello_world.py 

TROUBLESHOOTING

  • do you have OPENAI_API_KEY set?

PART 2: Create an agent with tools

Add OAK as a dependency

Next we will add OAK

uv add oaklib

TROUBLESHOOTING

You may need to do this first:

uv add fastobo --binary fastobo==0.12.3

Then create a file src/agent_tutorial/oak_agent.py

We will make an agent, as before

oak_agent = Agent(  
    'openai:gpt-4o',
    system_prompt="""
    You are an expert ontology curator. Use the ontologies at your disposal to
    answer the users questions.
    """,  
)```

But this time we will give an agent a *tool*

```python
@oak_agent.tool_plain
async def search_uberon(term: str) -> List[Tuple[str, str]]:
    """
    Search the UBERON ontology for a term.

    Note that search should take into account synonyms, but synonyms may be incomplete,
    so if you cannot find a concept of interest, try searching using related or synonymous
    terms.

    If you are searching for a composite term, try searching on the sub-terms to get a sense
    of the terminology used in the ontology.

    Args:
        term: The term to search for.

    Returns:
        A list of tuples, each containing an UBERON ID and a label.
    """
    adapter = get_adapter("ols:uberon")
    results = adapter.basic_search(term)
    labels = list(adapter.labels(results))
    print(f"## Query: {term} -> {labels}")
    return labels

Here we are using the OAK OLS adapter, configured to query Uberon on OLS

We can test this with

query = "What is the UBERON ID for the CNS?"
result = oak_agent.run_sync(query)

And run it:

uv run src/agent_tutorial/oak_agent.py 

Try this with some other terms. How well does it work?

PART 3: Create an annotator agent

Then create a file src/agent_tutorial/annotator_agent.py

We will create a bespoke data model for this agent:

class TextAnnotation(BaseModel):
    """
    A text annotation is a span of text and the UBERON ID and label for the anatomical structure it mentions.
    Use `text` for the source text, and `uberon_id` and `uberon_label` for the UBERON ID and label of the anatomical structure in the ontology.
    """
    text: str
    uberon_id: Optional[str] = None
    uberon_label: Optional[str] = None

class TextAnnotationResult(BaseModel):
    annotations: List[TextAnnotation]

Now we'll create an agent:

annotator_agent = Agent(  
    'claude-3-7-sonnet-latest',
    system_prompt="""
    Extract all uberon terms from the text. Return the as a list of annotations.
    Be sure to include all spans mentioning anatomical structures; if you cannot
    find a UBERON ID, then you should still return a TextAnnotation, just leave
    the uberon_id field empty.

    However, before giving up you should be sure to try different combinations of
    synonyms with the `search_uberon` tool.
    """,
    tools=[search_uberon],
    result_type=TextAnnotationResult,  
)

Note this reuses the tool from the previous example

And run it:

uv run src/agent_tutorial/annotator_agent.py 

Using a Proxy (e.g. CBORG)

cborg_api_key = os.environ.get("CBORG_API_KEY")

model = OpenAIModel(
    "anthropic/claude-sonnet",
    provider=OpenAIProvider(
        base_url="https://api.cborg.lbl.gov",
        api_key=cborg_api_key),
)

then, in place of code like:

agent = Agent(  
    'openai:gpt-4o',
    system_prompt='Be concise, reply with one sentence.',  
)

Do this:

agent = Agent(  
    model,
    system_prompt='Be concise, reply with one sentence.',  
)

Next Steps: Aurelian

After this, we invite you to check out aurelian and to try some of the ready-made agents and tools, and to contribute to this library!

Releases

No releases published

Packages

No packages published

Languages