Skip to content

Commit

Permalink
Merge pull request #118 from dvilelaf/fix/temperature
Browse files Browse the repository at this point in the history
Fix/temperature
  • Loading branch information
dvilelaf authored Dec 20, 2024
2 parents ae4bfbd + 20fcf18 commit da280d7
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 28 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ memeooorr
!packages/dvilela/services/memeooorr
packages/__pycache__/
packages/dvilela/connections/kv_store
packages/dvilela/connections/genai
packages/dvilela/protocols/kv_store
__pycache__/

Expand Down
6 changes: 3 additions & 3 deletions packages/dvilela/agents/memeooorr/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ connections:
- dvilela/twikit:0.1.0:bafybeig2rrxb4v56r7oo3vb5ahgryb7aw6n2i6wreackeamlhndwoldawm
- dvilela/kv_store:0.1.0:bafybeiekugvb2kan4342hliluxl3h5och3fjwqoafdyttpcn57evvyztq4
- valory/http_server:0.22.0:bafybeihpgu56ovmq4npazdbh6y6ru5i7zuv6wvdglpxavsckyih56smu7m
- dvilela/genai:0.1.0:bafybeifcrrfz6jwp437zutmrhtjjkruflauoa4go627c47haiv2r2ej2uq
- dvilela/genai:0.1.0:bafybeidkxxlonrxirznivkmzc34wmby4e4s57rfg2b7k6xyos23g3y6cdy
contracts:
- valory/gnosis_safe:0.1.0:bafybeiaw4yr7ubqlp63iz5wxqep3a5fokqs3kqva7sp2nsqg355zzucqgm
- valory/gnosis_safe_proxy_factory:0.1.0:bafybeidkqhw7smq4kbqryodom6maj7gubc5nbxwm4vi343xbkqxx3brjtm
Expand All @@ -41,8 +41,8 @@ skills:
- valory/transaction_settlement_abci:0.1.0:bafybeigh2vkt74jrad5gtsczrgqcuhcqe7jkgjy7jdw56yamlzwwnaymjy
- valory/registration_abci:0.1.0:bafybeib3n6vqkfbrcubcbliebjnuwyywdinxkbzt76n6gbn2kg7ace47dq
- valory/reset_pause_abci:0.1.0:bafybeihkj6lmaypspyxe5qqrjgnolyck62pyvqoylr24ab6ue4steqcw7e
- dvilela/memeooorr_abci:0.1.0:bafybeidcqpydciwahw5f56k4hlqm5gbcaqvqolbhbbv2ogljecqa5a7rvm
- dvilela/memeooorr_chained_abci:0.1.0:bafybeibytcdn746izbyeosfz4sidkcbdk4h6dytmnjvbqtnonitosochx4
- dvilela/memeooorr_abci:0.1.0:bafybeidukrur67t3mcuhjhynwxgyi6ymida7rq5sv3zcbejtn4mfwzlye4
- dvilela/memeooorr_chained_abci:0.1.0:bafybeics2karqqcryuqknarywkhoqkc2vqj2jhqkcbteeiajzpfvktec4y
default_ledger: ethereum
required_ledgers:
- ethereum
Expand Down
21 changes: 21 additions & 0 deletions packages/dvilela/connections/genai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2021-2024 Valory AG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""Genai connection."""
230 changes: 230 additions & 0 deletions packages/dvilela/connections/genai/connection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ------------------------------------------------------------------------------
#
# Copyright 2021-2024 David Vilela Freire
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ------------------------------------------------------------------------------

"""Genai connection."""

import json
import time
from datetime import datetime, timezone
from typing import Any, Dict, Tuple, cast

import google.generativeai as genai # type: ignore
from aea.configurations.base import PublicId
from aea.connections.base import BaseSyncConnection
from aea.mail.base import Envelope
from aea.protocols.base import Address, Message
from aea.protocols.dialogue.base import Dialogue

from packages.valory.protocols.srr.dialogues import SrrDialogue
from packages.valory.protocols.srr.dialogues import SrrDialogues as BaseSrrDialogues
from packages.valory.protocols.srr.message import SrrMessage


PUBLIC_ID = PublicId.from_str("dvilela/genai:0.1.0")

DEFAULT_TEMPERATURE = 2.0


class SrrDialogues(BaseSrrDialogues):
"""A class to keep track of SRR dialogues."""

def __init__(self, **kwargs: Any) -> None:
"""
Initialize dialogues.
:param kwargs: keyword arguments
"""

def role_from_first_message( # pylint: disable=unused-argument
message: Message, receiver_address: Address
) -> Dialogue.Role:
"""Infer the role of the agent from an incoming/outgoing first message
:param message: an incoming/outgoing first message
:param receiver_address: the address of the receiving agent
:return: The role of the agent
"""
return SrrDialogue.Role.CONNECTION

BaseSrrDialogues.__init__(
self,
self_address=str(kwargs.pop("connection_id")),
role_from_first_message=role_from_first_message,
**kwargs,
)


class GenaiConnection(BaseSyncConnection):
"""Proxy to the functionality of the Genai library."""

MAX_WORKER_THREADS = 1

connection_id = PUBLIC_ID

def __init__(self, *args: Any, **kwargs: Any) -> None: # pragma: no cover
"""
Initialize the connection.
The configuration must be specified if and only if the following
parameters are None: connection_id, excluded_protocols or restricted_to_protocols.
Possible arguments:
- configuration: the connection configuration.
- data_dir: directory where to put local files.
- identity: the identity object held by the agent.
- crypto_store: the crypto store for encrypted communication.
- restricted_to_protocols: the set of protocols ids of the only supported protocols for this connection.
- excluded_protocols: the set of protocols ids that we want to exclude for this connection.
:param args: arguments passed to component base
:param kwargs: keyword arguments passed to component base
"""
super().__init__(*args, **kwargs)
genai_api_key = self.configuration.config.get("genai_api_key")
genai.configure(api_key=genai_api_key)
self.last_call = datetime.now(timezone.utc)

self.dialogues = SrrDialogues(connection_id=PUBLIC_ID)

def main(self) -> None:
"""
Run synchronous code in background.
SyncConnection `main()` usage:
The idea of the `main` method in the sync connection
is to provide for a way to actively generate messages by the connection via the `put_envelope` method.
A simple example is the generation of a message every second:
```
while self.is_connected:
envelope = make_envelope_for_current_time()
self.put_enevelope(envelope)
time.sleep(1)
```
In this case, the connection will generate a message every second
regardless of envelopes sent to the connection by the agent.
For instance, this way one can implement periodically polling some internet resources
and generate envelopes for the agent if some updates are available.
Another example is the case where there is some framework that runs blocking
code and provides a callback on some internal event.
This blocking code can be executed in the main function and new envelops
can be created in the event callback.
"""

def on_send(self, envelope: Envelope) -> None:
"""
Send an envelope.
:param envelope: the envelope to send.
"""
srr_message = cast(SrrMessage, envelope.message)

dialogue = self.dialogues.update(srr_message)

if srr_message.performative != SrrMessage.Performative.REQUEST:
self.logger.error(
f"Performative `{srr_message.performative.value}` is not supported."
)
return

payload, error = self._get_response(
payload=json.loads(srr_message.payload),
)

response_message = cast(
SrrMessage,
dialogue.reply( # type: ignore
performative=SrrMessage.Performative.RESPONSE,
target_message=srr_message,
payload=json.dumps(payload),
error=error,
),
)

response_envelope = Envelope(
to=envelope.sender,
sender=envelope.to,
message=response_message,
context=envelope.context,
)

self.put_envelope(response_envelope)

def _get_response(self, payload: dict) -> Tuple[Dict, bool]:
"""Get response from Genai."""

AVAILABLE_MODELS = [
"gemini-1.5-flash",
"gemini-1.5-pro",
"gemini-2.0-flash-exp",
]
REQUIRED_PROPERTIES = ["prompt"]

if not all(i in payload for i in REQUIRED_PROPERTIES):
return {
"error": f"Some parameter is missing from the request data: required={REQUIRED_PROPERTIES}, got={list(payload.keys())}"
}, True

self.logger.info(f"Calling genai: {payload}")

model_name = payload.get("model", "gemini-1.5-flash")

if model_name not in AVAILABLE_MODELS:
return {
"error": f"Model {model_name} is not an available model [{AVAILABLE_MODELS}]"
}, True

model = genai.GenerativeModel(model_name)

try:
# Avoid calling more than 1 time every 5 seconds (API limit is 15 req/min for flash)
while (datetime.now(timezone.utc) - self.last_call).total_seconds() < 5:
time.sleep(1)

temperature = payload.get("temperature", None)
if temperature is None:
temperature = DEFAULT_TEMPERATURE

response = model.generate_content(
payload["prompt"],
generation_config=genai.types.GenerationConfig(
temperature=temperature,
),
)
self.logger.info(f"LLM response: {response.text}")
self.last_call = datetime.now(timezone.utc)
except Exception as e:
return {"error": f"Exception while calling Genai:\n{e}"}, True

return {"response": response.text}, False # type: ignore

def on_connect(self) -> None:
"""
Tear down the connection.
Connection status set automatically.
"""

def on_disconnect(self) -> None:
"""
Tear down the connection.
Connection status set automatically.
"""
25 changes: 25 additions & 0 deletions packages/dvilela/connections/genai/connection.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: genai
author: dvilela
version: 0.1.0
type: connection
description: A connection that provides a wrapper around the genai library.
license: Apache-2.0
aea_version: '>=1.0.0, <2.0.0'
fingerprint:
__init__.py: bafybeibql5vfopyoqyoxec6wevmmfbabws2mbpvyw4j5llvbdgxiqzhk7e
connection.py: bafybeieyyadzvfafxgdrlyswrh6kntnrgff7n6hzkdpqlmeehhlgg3ltxi
readme.md: bafybeiaulo2wb7znrotpnsh27idv2j3rlmslene7l3ygedjmshyna6tkxu
fingerprint_ignore_patterns: []
connections: []
protocols:
- valory/srr:0.1.0:bafybeihrixgptxuqpf2s4nujypwlv5aed2nboozq5kl4c26cxw6r7si2x4
class_name: GenaiConnection
config:
genai_api_key: null
excluded_protocols: []
restricted_to_protocols: []
dependencies:
google-generativeai:
version: ==0.8.2
is_abstract: false
cert_requests: []
3 changes: 3 additions & 0 deletions packages/dvilela/connections/genai/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Llama connection

The Llama connection provides a wrapper around Llama-cpp-python library.
2 changes: 1 addition & 1 deletion packages/dvilela/services/memeooorr/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license: Apache-2.0
fingerprint:
README.md: bafybeiaekcmielp6mb4qvmo2twwkpmoun36bqajrh7wnnkcpdnia45ycl4
fingerprint_ignore_patterns: []
agent: dvilela/memeooorr:0.1.0:bafybeihmrflznbs4zzkw4cqgkvw5clfor7mzop3vkdou653tbbnuc3442m
agent: dvilela/memeooorr:0.1.0:bafybeiatj2s6aobvigotwzhjr4nu44ebiiire224dtu5gqkwpuw6dcfpc4
number_of_agents: 1
deployment:
agent:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,20 @@ def _call_twikit(self, method: str, **kwargs: Any) -> Generator[None, None, Any]
def _call_genai(
self,
prompt: str,
temperature: Optional[float] = None,
) -> Generator[None, None, Optional[str]]:
"""Send a request message from the skill context."""

payload_data: Dict[str, Any] = {"prompt": prompt}

if temperature is not None:
payload_data["temperature"] = temperature

srr_dialogues = cast(SrrDialogues, self.context.srr_dialogues)
srr_message, srr_dialogue = srr_dialogues.create(
counterparty=str(GENAI_CONNECTION_PUBLIC_ID),
performative=SrrMessage.Performative.REQUEST,
payload=json.dumps({"prompt": prompt}),
payload=json.dumps(payload_data),
)
srr_message = cast(SrrMessage, srr_message)
srr_dialogue = cast(SrrDialogue, srr_dialogue)
Expand Down
4 changes: 2 additions & 2 deletions packages/dvilela/skills/memeooorr_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ aea_version: '>=1.0.0, <2.0.0'
fingerprint:
__init__.py: bafybeidorrnxjv4n4ngovxnu4mzod46kyrdncfmli4hapqeqnzp7imq7hm
behaviour_classes/__init__.py: bafybeicjks4kxsb2r6a4armmaqxyxngwm3pouegq3fycm37rbe7otiwsre
behaviour_classes/base.py: bafybeidrog7oqe6cdrbx66mgsiqfu7ybuuexkruqhwmmoz3bu34p2f56nq
behaviour_classes/base.py: bafybeicwvdmdyfjvwv7htgfwda5n6rbypdp3vev5lftclvhqyeq2nutf6m
behaviour_classes/chain.py: bafybeigxfwko3rofqlzyjjhgeo6yabxseqngo2uz5muyfk3f2jjpgdrsli
behaviour_classes/db.py: bafybeieuhjes2gsiidepjxcojgnn3swx2znem5uwvz7rwkxpwls3dmlxf4
behaviour_classes/llm.py: bafybeifdhipccrdtfx5vay2sfd7vss4iovwtyeefuz5vrjewjbyatk35c4
Expand All @@ -26,7 +26,7 @@ fingerprint_ignore_patterns: []
connections:
- dvilela/kv_store:0.1.0:bafybeiekugvb2kan4342hliluxl3h5och3fjwqoafdyttpcn57evvyztq4
- dvilela/twikit:0.1.0:bafybeig2rrxb4v56r7oo3vb5ahgryb7aw6n2i6wreackeamlhndwoldawm
- dvilela/genai:0.1.0:bafybeifcrrfz6jwp437zutmrhtjjkruflauoa4go627c47haiv2r2ej2uq
- dvilela/genai:0.1.0:bafybeidkxxlonrxirznivkmzc34wmby4e4s57rfg2b7k6xyos23g3y6cdy
- valory/http_server:0.22.0:bafybeihpgu56ovmq4npazdbh6y6ru5i7zuv6wvdglpxavsckyih56smu7m
contracts:
- valory/gnosis_safe:0.1.0:bafybeiaw4yr7ubqlp63iz5wxqep3a5fokqs3kqva7sp2nsqg355zzucqgm
Expand Down
2 changes: 1 addition & 1 deletion packages/dvilela/skills/memeooorr_chained_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ skills:
- valory/reset_pause_abci:0.1.0:bafybeihkj6lmaypspyxe5qqrjgnolyck62pyvqoylr24ab6ue4steqcw7e
- valory/transaction_settlement_abci:0.1.0:bafybeigh2vkt74jrad5gtsczrgqcuhcqe7jkgjy7jdw56yamlzwwnaymjy
- valory/termination_abci:0.1.0:bafybeifi2uodnrjsrivj53g3sjutocmyusbx6mlsb6oanqdyt2mfbyvusy
- dvilela/memeooorr_abci:0.1.0:bafybeidcqpydciwahw5f56k4hlqm5gbcaqvqolbhbbv2ogljecqa5a7rvm
- dvilela/memeooorr_abci:0.1.0:bafybeidukrur67t3mcuhjhynwxgyi6ymida7rq5sv3zcbejtn4mfwzlye4
behaviours:
main:
args: {}
Expand Down
10 changes: 5 additions & 5 deletions packages/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
"contract/dvilela/meme_factory/0.1.0": "bafybeifwx7zcrj7fi4nkfdcucomn3ph7jlr3ac364ilayzcnh4sqjma3vu",
"contract/dvilela/service_registry/0.1.0": "bafybeie2rrgzcjehlp2feff6bhkuindxzrnuwxe2jcrsy2thcdtrsp2o24",
"connection/dvilela/twikit/0.1.0": "bafybeig2rrxb4v56r7oo3vb5ahgryb7aw6n2i6wreackeamlhndwoldawm",
"skill/dvilela/memeooorr_abci/0.1.0": "bafybeidcqpydciwahw5f56k4hlqm5gbcaqvqolbhbbv2ogljecqa5a7rvm",
"skill/dvilela/memeooorr_chained_abci/0.1.0": "bafybeibytcdn746izbyeosfz4sidkcbdk4h6dytmnjvbqtnonitosochx4",
"agent/dvilela/memeooorr/0.1.0": "bafybeihmrflznbs4zzkw4cqgkvw5clfor7mzop3vkdou653tbbnuc3442m",
"service/dvilela/memeooorr/0.1.0": "bafybeida3qb2cuqcyanpfkf6do7ttyzi6erq54t4y3dz7fcfhy2yo3iw5y"
"connection/dvilela/genai/0.1.0": "bafybeidkxxlonrxirznivkmzc34wmby4e4s57rfg2b7k6xyos23g3y6cdy",
"skill/dvilela/memeooorr_abci/0.1.0": "bafybeidukrur67t3mcuhjhynwxgyi6ymida7rq5sv3zcbejtn4mfwzlye4",
"skill/dvilela/memeooorr_chained_abci/0.1.0": "bafybeics2karqqcryuqknarywkhoqkc2vqj2jhqkcbteeiajzpfvktec4y",
"agent/dvilela/memeooorr/0.1.0": "bafybeiatj2s6aobvigotwzhjr4nu44ebiiire224dtu5gqkwpuw6dcfpc4",
"service/dvilela/memeooorr/0.1.0": "bafybeiedbttrmwpdxzr5krp5bbt5jkdh4tsy7kewhrok3d557qjvje35iy"
},
"third_party": {
"protocol/open_aea/signing/1.0.0": "bafybeihv62fim3wl2bayavfcg3u5e5cxu3b7brtu4cn5xoxd6lqwachasi",
Expand Down Expand Up @@ -36,7 +37,6 @@
"connection/valory/p2p_libp2p_client/0.1.0": "bafybeid3xg5k2ol5adflqloy75ibgljmol6xsvzvezebsg7oudxeeolz7e",
"connection/valory/http_server/0.22.0": "bafybeihpgu56ovmq4npazdbh6y6ru5i7zuv6wvdglpxavsckyih56smu7m",
"connection/dvilela/kv_store/0.1.0": "bafybeiekugvb2kan4342hliluxl3h5och3fjwqoafdyttpcn57evvyztq4",
"connection/dvilela/genai/0.1.0": "bafybeifcrrfz6jwp437zutmrhtjjkruflauoa4go627c47haiv2r2ej2uq",
"skill/valory/abstract_abci/0.1.0": "bafybeieo7pe5wqjphs5izpz5aujjbubymlxub62b3rhx6yglu65ibalffu",
"skill/valory/reset_pause_abci/0.1.0": "bafybeihkj6lmaypspyxe5qqrjgnolyck62pyvqoylr24ab6ue4steqcw7e",
"skill/valory/registration_abci/0.1.0": "bafybeib3n6vqkfbrcubcbliebjnuwyywdinxkbzt76n6gbn2kg7ace47dq",
Expand Down
Loading

0 comments on commit da280d7

Please sign in to comment.