Documentation and tutorials for futurehouse-client, a client for interacting with endpoints of the FutureHouse platform.
- Installation
- Quickstart
- Functionalities
- Authentication
- Simple task running
- Task Continuation
- Asynchronous tasks
uv pip install futurehouse-client
from futurehouse_client import FutureHouseClient, JobNames
from pathlib import Path
from aviary.core import DummyEnv
import ldp
client = FutureHouseClient(
api_key="your_api_key",
)
task_data = {
"name": JobNames.CROW,
"query": "Which neglected diseases had a treatment developed by artificial intelligence?",
}
task_response = client.run_tasks_until_done(task_data)
A quickstart example can be found in the client_notebook.ipynb file, where we show how to submit and retrieve a task, pass runtime configuration to the agent, and ask follow-up questions to the previous task.
FutureHouse client implements a RestClient (called FutureHouseClient
) with the following functionalities:
- Simple task running:
run_tasks_until_done(TaskRequest)
orawait arun_tasks_until_done(TaskRequest)
- Asynchronous tasks:
get_task(task_id)
oraget_task(task_id)
andcreate_task(TaskRequest)
oracreate_task(TaskRequest)
To create a FutureHouseClient
, you need to pass a FutureHouse platform api key (see Authentication):
from futurehouse_client import FutureHouseClient
client = FutureHouseClient(
api_key="your_api_key",
)
In order to use the FutureHouseClient
, you need to authenticate yourself. Authentication is done by providing an API key, which can be obtained directly from your profile page in the FutureHouse platform.
In the FutureHouse platform, we define the deployed combination of an agent and an environment as a job
. To invoke a job, we need to submit a task
(also called a query
) to it.
FutureHouseClient
can be used to submit tasks/queries to available jobs in the FutureHouse platform. Using a FutureHouseClient
instance, you can submit tasks to the platform by calling the create_task
method, which receives a TaskRequest
(or a dictionary with kwargs
) and returns the task id.
Aiming to make the submission of tasks as simple as possible, we have created a JobNames
enum
that contains the available task types.
The available supported jobs are:
Alias | Job Name | Task type | Description |
---|---|---|---|
JobNames.CROW |
job-futurehouse-paperqa2 |
Fast Search | Ask a question of scientific data sources, and receive a high-accuracy, cited response. Built with PaperQA2. |
JobNames.FALCON |
job-futurehouse-paperqa2-deep |
Deep Search | Use a plethora of sources to deeply research. Receive a detailed, structured report as a response. |
JobNames.OWL |
job-futurehouse-hasanyone |
Precedent Search | Formerly known as HasAnyone, query if anyone has ever done something in science. |
JobNames.PHOENIX |
job-futurehouse-phoenix |
Chemistry Tasks | A new iteration of ChemCrow, Phoenix uses cheminformatics tools to do chemistry. Good for planning synthesis and design of new molecules. |
JobNames.DUMMY |
job-futurehouse-dummy |
Dummy Task | This is a dummy task. Mainly for testing purposes. |
Using JobNames
, the task submission looks like this:
from futurehouse_client import FutureHouseClient, JobNames
client = FutureHouseClient(
api_key="your_api_key",
)
task_data = {
"name": JobNames.OWL,
"query": "Has anyone tested therapeutic exerkines in humans or NHPs?",
}
task_response = client.run_tasks_until_done(task_data)
print(task_response.answer)
Or if running async code:
import asyncio
from futurehouse_client import FutureHouseClient, JobNames
async def main():
client = FutureHouseClient(
api_key="your_api_key",
)
task_data = {
"name": JobNames.OWL,
"query": "Has anyone tested therapeutic exerkines in humans or NHPs?",
}
task_response = await client.arun_tasks_until_done(task_data)
print(task_response.answer)
return task_id
# For Python 3.7+
if __name__ == "__main__":
task_id = asyncio.run(main())
Note that in either the sync or the async code, collections of tasks can be given to the client to run them in a batch:
import asyncio
from futurehouse_client import FutureHouseClient, JobNames
async def main():
client = FutureHouseClient(
api_key="your_api_key",
)
task_data = [{
"name": JobNames.OWL,
"query": "Has anyone tested therapeutic exerkines in humans or NHPs?",
},
{
"name": JobNames.CROW,
"query": "Are there any clinically validated therapeutic exerkines for humans?",
}
]
task_responses = await client.arun_tasks_until_done(task_data)
print(task_responses[0].answer)
print(task_responses[1].answer)
return task_id
# For Python 3.7+
if __name__ == "__main__":
task_id = asyncio.run(main())
TaskRequest
can also be used to submit jobs and it has the following fields:
Field | Type | Description |
---|---|---|
id | UUID | Optional job identifier. A UUID will be generated if not provided |
name | str | Name of the job to execute eg. job-futurehouse-paperqa2 , or using the JobNames for convenience: JobNames.CROW |
query | str | Query or task to be executed by the job |
runtime_config | RuntimeConfig | Optional runtime parameters for the job |
runtime_config
can receive a AgentConfig
object with the desired kwargs. Check the available AgentConfig
fields in the LDP documentation. Besides the AgentConfig
object, we can also pass timeout
and max_steps
to limit the execution time and the number of steps the agent can take.
from futurehouse_client import FutureHouseClient, JobNames
from futurehouse_client.models.app import TaskRequest
client = FutureHouseClient(
api_key="your_api_key",
)
task_response = client.run_tasks_until_done(
TaskRequest(
name=JobNames.OWL,
query="Has anyone tested therapeutic exerkines in humans or NHPs?",
)
)
print(task_response.answer)
A TaskResponse
will be returned from using our agents. For Owl, Crow, and Falcon, we default to a subclass, PQATaskResponse
which has some key attributes:
Field | Type | Description |
---|---|---|
answer | str | Answer to your query. |
formatted_answer | str | Specially formatted answer with references. |
has_successful_answer | bool | Flag for whether the agent was able to find a good answer to your query or not. |
If using the verbose
setting, much more data can be pulled down from your TaskResponse
, which will exist across all agents (not just Owl, Crow, and Falcon).
from futurehouse_client import FutureHouseClient, JobNames
from futurehouse_client.models.app import TaskRequest
client = FutureHouseClient(
api_key="your_api_key",
)
task_response = client.run_tasks_until_done(
TaskRequest(
name=JobNames.OWL,
query="Has anyone tested therapeutic exerkines in humans or NHPs?",
),
verbose=True,
)
print(task_response.environment_frame)
In that case, a TaskResponseVerbose
will have the following fields:
Field | Type | Description |
---|---|---|
agent_state | dict | Large object with all agent states during the progress of your task. |
environment_frame | dict | Large nested object with all environment data, for PQA environments it includes contexts, paper metadata, and answers. |
metadata | dict | Extra metadata about your query. |
Once a task is submitted and the answer is returned, FutureHouse platform allow you to ask follow-up questions to the previous task.
It is also possible through the platform API.
To accomplish that, we can use the runtime_config
we discussed in the Simple task running section.
from futurehouse_client import FutureHouseClient, JobNames
client = FutureHouseClient(
api_key="your_api_key",
)
task_data = {"name": JobNames.CROW, "query": "How many species of birds are there?"}
task_id = client.create_task(task_data)
continued_task_data = {
"name": JobNames.CROW,
"query": "From the previous answer, specifically,how many species of crows are there?",
"runtime_config": {"continued_job_id": task_id},
}
task_result = client.run_tasks_until_done(continued_task_data)
Sometimes you may want to submit many jobs, while querying results at a later time. In this way you can do other things while waiting for a response. The platform API supports this as well rather than waiting for a result.
from futurehouse_client import FutureHouseClient
client = FutureHouseClient(
api_key="your_api_key",
)
task_data = {"name": JobNames.CROW, "query": "How many species of birds are there?"}
task_id = client.create_task(task_data)
# move on to do other things
task_status = client.get_task(task_id)
task_status
contains information about the task. For instance, its status
, task
, environment_name
and agent_name
, and other fields specific to the job. You can continually query the status until it's success
before moving on.