Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: finbert integration with uagents #151

Merged
merged 1 commit into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions integrations/finbert/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Finbert Integration

FinBERT is a pre-trained NLP model to analyze sentiment of financial text. It is built by further training the BERT language model in the finance domain, using a large financial corpus and thereby fine-tuning it for financial sentiment classification.

Ensure you have the following software installed:

- Python (v3.10+ recommended)
- Poetry (A Python packaging and dependency management tool)

## Setup

1. For the demo to work, you need to get HuggingFaceAPI Token:

1. Visit [HuggingFace](https://huggingface.co/).
2. Sign up or log in.
3. Navigate to `Profile -> Settings -> Access Tokens`.
4. Copy an existing token or create a new one.

2. In the `finbert/src` directory, create a `.env` file and set your HuggingFaceAPI Token:

```
export HUGGING_FACE_ACCESS_TOKEN="{Your HuggingFaceAPI Token}"
```

3. To load the environment variables from `.env` and install the dependencies:

```bash
cd src
source .env
poetry install
```

## Running The Script

To run the project, use the command:

```
poetry run python main.py
```

In the console look for the following output:

```
Adding agent to Bureau: {agent_address}

```

Copy the {agent_address} address and replace **AI_MODEL_AGENT_ADDRESS** value in agents/finbert_user.py.


You can change the input text to what you like, just open the src/finbert_user.py file, and change the value of **INPUT_TEXT** variable in agents/finbert_user.py.

The finbert model will give softmax outputs for three labels: positive, negative or neutral.
1,233 changes: 1,233 additions & 0 deletions integrations/finbert/poetry.lock

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions integrations/finbert/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tool.poetry]
name = "finbert-integration"
version = "0.0.1"
description = "showcasing finbert integration with uagents"
authors = ["Sangram Singh"]

[tool.poetry.dependencies]
python = ">=3.10,<3.12"
uagents = "*"
requests = "^2.31.0"
Empty file.
Empty file.
74 changes: 74 additions & 0 deletions integrations/finbert/src/agents/finbert_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Necessary imports: uagents for agent creation and message handling,
# os and requests for managing API calls
from uagents import Agent, Context, Protocol
from messages.basic import UAResponse, UARequest, Error
from uagents.setup import fund_agent_if_low
import os
import requests

# The access token and URL for the FinBERT model, served by Hugging Face
HUGGING_FACE_ACCESS_TOKEN = os.getenv(
"HUGGING_FACE_ACCESS_TOKEN", "HUGGING FACE secret phrase :)")
FINBERT_URL = "https://api-inference.huggingface.co/models/ProsusAI/finbert"

# Setting the headers for the API call
HEADERS = {
"Authorization": f"Bearer {HUGGING_FACE_ACCESS_TOKEN}"
}

# Creating the agent and funding it if necessary
agent = Agent(
name="finbert_agent",
seed=HUGGING_FACE_ACCESS_TOKEN,
port=8001,
endpoint=["http://127.0.0.1:8001/submit"],
)
fund_agent_if_low(agent.wallet.address())

# Function to get classification results from FinBERT for a given text


async def get_classification(ctx: Context, sender: str, text: str):
data = {
"inputs": text
}

try:
# Making POST request to Hugging Face FinBERT API
response = requests.post(FINBERT_URL, headers=HEADERS, json=data)

if response.status_code != 200:
# Error handling - send error message back to user if API call unsuccessful
await ctx.send(sender, Error(error=f"Error: {response.json().get('error')}"))
return
# If API call is successful, return the response from the model
model_res = response.json()[0]
await ctx.send(sender, UAResponse(response=model_res))
return
except Exception as ex:
# Catch and notify any exception occured during API call or data handling
await ctx.send(sender, Error(error=f"An exception occurred while processing the request: {ex}"))
return


# Protocol declaration for UARequests
finbert_agent = Protocol("UARequest")
jrriehl marked this conversation as resolved.
Show resolved Hide resolved

# Declaration of a message event handler for handling UARequests and send respective response.


@finbert_agent.on_message(model=UARequest, replies={UAResponse, Error})
async def handle_request(ctx: Context, sender: str, request: UARequest):
# Logging the request information
ctx.logger.info(
f"Got request from {sender} for text classification : {request.text}")

# Call text classification function for the incoming request's text
await get_classification(ctx, sender, request.text)

# Include protocol to the agent
agent.include(finbert_agent)
jrriehl marked this conversation as resolved.
Show resolved Hide resolved

# If the script is run as the main program, run our agents event loop
if __name__ == "__main__":
finbert_agent.run()
39 changes: 39 additions & 0 deletions integrations/finbert/src/agents/finbert_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from uagents import Agent, Context, Protocol # Import necessary modules
from messages.basic import UAResponse, UARequest, Error # Import Basic messages
# Import the fund_agent_if_low function
from uagents.setup import fund_agent_if_low
import os # Import os for environment variables if any needed

INPUT_TEXT = "Stocks rallied and the British pound gained."
AI_MODEL_AGENT_ADDRESS = "agent1q2gdm20yg3krr0k5nt8kf794ftm46x2cs7xyrm2gqc9ga5lulz9xsp4l4kk"

user = Agent(
name="finbert_user",
port=8000,
endpoint=["http://127.0.0.1:8000/submit"],
)

fund_agent_if_low(user.wallet.address())

finbert_user = Protocol("Request")
jrriehl marked this conversation as resolved.
Show resolved Hide resolved


@finbert_user.on_interval(360, messages=UARequest)
async def text_classification(ctx: Context):
ctx.logger.info(f"Asking AI model agent to classify: {INPUT_TEXT}")
await ctx.send(AI_MODEL_AGENT_ADDRESS, UARequest(text=INPUT_TEXT))


@finbert_user.on_message(model=UAResponse)
async def handle_data(ctx: Context, sender: str, data: UAResponse):
ctx.logger.info(f"Got response from AI model agent: {data.response}")


@finbert_user.on_message(model=Error)
async def handle_error(ctx: Context, sender: str, error: Error):
ctx.logger.info(f"Got error from AI model agent: {error}")

user.include(finbert_user)
jrriehl marked this conversation as resolved.
Show resolved Hide resolved

if __name__ == "__main__":
finbert_user.run()
13 changes: 13 additions & 0 deletions integrations/finbert/src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from uagents import Bureau

from agents.finbert_agent import agent
from agents.finbert_user import user


if __name__ == "__main__":
bureau = Bureau(endpoint="http://127.0.0.1:8000/submit", port=8000)
print(f"Adding agent to Bureau: {agent.address}")
bureau.add(agent)
print(f"Adding user agent to Bureau: {user.address}")
bureau.add(user)
bureau.run()
Empty file.
13 changes: 13 additions & 0 deletions integrations/finbert/src/messages/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from uagents import Model


class UARequest(Model):
text: str


class Error(Model):
error: str


class UAResponse(Model):
response: list