From 24a7d8ba1d94fa25c0d6c5db33b38853bc2d5ff2 Mon Sep 17 00:00:00 2001 From: Marco Perini Date: Mon, 11 Nov 2024 10:27:44 +0100 Subject: [PATCH 1/7] docs: imporeved docs and ttl_output method --- README.md | 20 ++++++++++---------- brickllm/graphs/abstract_graph.py | 13 +++++-------- brickllm/graphs/brickschema_graph.py | 2 ++ brickllm/graphs/brickschema_graph_local.py | 2 ++ 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 737ebfb..3b6584b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ BrickLLM is a Python library for generating RDF files following the BrickSchema ontology using Large Language Models (LLMs). -## Features +## 🚀 Features - Generate BrickSchema-compliant RDF files from natural language descriptions of buildings and facilities - Support for multiple LLM providers (OpenAI, Anthropic, Fireworks) @@ -224,12 +224,12 @@ brick_graph_local.save_ttl_output("my_building_local.ttl") ## 📖 Documentation -For more detailed information on how to use BrickLLM, please refer to our [documentation](https://brickllm.com/docs). +For more detailed information on how to use BrickLLM, please refer to our [documentation](https://eurac-eebgroup.github.io/brick-llm/). ## ▶️ Web Application -A web app is available to use the library directly through an interface at the following link (). -The application can also be used locally as described in the dedicated repository [BrickLLM App](https://github.com/EURAC-EEBgroup/Brick_ontology_tool). +A web app is available to use the library directly through an interface at the following link (). +The application can also be used locally as described in the dedicated repository [BrickLLM App](https://github.com/EURAC-EEBgroup/Brick_ontology_tool). **Note**: The tool is currently being deployed on our servers and on the MODERATE platform. It will be online shortly ! @@ -241,7 +241,7 @@ We welcome contributions to BrickLLM! Please see our [contributing guidelines](C BrickLLM is released under the BSD-3-Clause License. See the [LICENSE](LICENSE) file for details. -## Contact +## 📧 Contact For any questions or support, please contact: @@ -249,17 +249,17 @@ For any questions or support, please contact: - Daniele Antonucci - Rocco Giudice -## Citation +## 📝 Citation Please cite us if you use the library - + [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14039358.svg)](https://zenodo.org/doi/10.5281/zenodo.14039358) -## 💙 Aknwoledegments -This work was carried out within European projects: +## 💙 Acknowledgements +This work was carried out within European projects:

- Moderate Moderate - Horizon Europe research and innovation programme under grant agreement No 101069834, with the aim of contributing to the development of open products useful for defining plausible scenarios for the decarbonization of the built environment diff --git a/brickllm/graphs/abstract_graph.py b/brickllm/graphs/abstract_graph.py index bde38c8..c9ef276 100644 --- a/brickllm/graphs/abstract_graph.py +++ b/brickllm/graphs/abstract_graph.py @@ -16,6 +16,7 @@ def __init__(self, model: Union[str, BaseChatModel] = "openai"): self.graph = None self.config = {"configurable": {"thread_id": "1", "llm_model": self.model}} self.result = None + self.ttl_output = None @abstractmethod def build_graph(self): @@ -75,12 +76,8 @@ def save_ttl_output(self, output_file: str = "brick_schema_output.ttl") -> None: if self.result is None: raise ValueError("No result found. Please run the graph first.") - ttl_output = self.result.get("ttl_output", None) + if self.ttl_output is None: + raise ValueError("No TTL output found. Please run the graph first.") - if ttl_output: - with open(output_file, "w") as f: - f.write(ttl_output) - else: - raise ValueError( - "No TTL output found in the result. Please run the graph with a valid prompt." - ) + with open(output_file, "w") as f: + f.write(self.ttl_output) diff --git a/brickllm/graphs/brickschema_graph.py b/brickllm/graphs/brickschema_graph.py index 7e62c1a..1c9c960 100644 --- a/brickllm/graphs/brickschema_graph.py +++ b/brickllm/graphs/brickschema_graph.py @@ -56,7 +56,9 @@ def run( ): events.append(event) self.result = events[-1] + self.ttl_output = self.result.get("ttl_output", None) return events else: self.result = self.graph.invoke(input_data, self.config) + self.ttl_output = self.result.get("ttl_output", None) return self.result diff --git a/brickllm/graphs/brickschema_graph_local.py b/brickllm/graphs/brickschema_graph_local.py index 6301115..3b7a8bb 100644 --- a/brickllm/graphs/brickschema_graph_local.py +++ b/brickllm/graphs/brickschema_graph_local.py @@ -42,7 +42,9 @@ def run( ): events.append(event) self.result = events[-1] + self.ttl_output = self.result.get("ttl_output", None) return events else: self.result = self.graph.invoke(input_data, self.config) + self.ttl_output = self.result.get("ttl_output", None) return self.result From d83e66f5851a4db71825c925389d3183cb10faaf Mon Sep 17 00:00:00 2001 From: Marco Perini Date: Mon, 11 Nov 2024 11:04:52 +0100 Subject: [PATCH 2/7] feat: ttl_to_building_description function --- README.md | 2 +- brickllm/__init__.py | 8 +++++++- brickllm/graphs/abstract_graph.py | 13 ++++++++++++- brickllm/helpers/__init__.py | 2 ++ brickllm/helpers/prompts.py | 28 ++++++++++++++++++++++------ brickllm/schemas.py | 9 +++++++++ brickllm/utils/__init__.py | 2 ++ brickllm/utils/ttl_to_prompt.py | 27 +++++++++++++++++++++++++++ examples/example_custom_llm.py | 9 +++++++++ examples/example_openai.py | 9 +++++++++ 10 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 brickllm/utils/ttl_to_prompt.py diff --git a/README.md b/README.md index 3b6584b..1ac0641 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ BrickLLM is a Python library for generating RDF files following the BrickSchema ontology using Large Language Models (LLMs). -## 🚀 Features +## 🧰 Features - Generate BrickSchema-compliant RDF files from natural language descriptions of buildings and facilities - Support for multiple LLM providers (OpenAI, Anthropic, Fireworks) diff --git a/brickllm/__init__.py b/brickllm/__init__.py index cdbd062..1a4e70a 100644 --- a/brickllm/__init__.py +++ b/brickllm/__init__.py @@ -1,11 +1,17 @@ from .configs import GraphConfig -from .schemas import ElemListSchema, RelationshipsSchema, TTLSchema +from .schemas import ( + ElemListSchema, + RelationshipsSchema, + TTLSchema, + TTLToBuildingPromptSchema, +) from .states import State, StateLocal __all__ = [ "ElemListSchema", "RelationshipsSchema", "TTLSchema", + "TTLToBuildingPromptSchema", "State", "StateLocal", "GraphConfig", diff --git a/brickllm/graphs/abstract_graph.py b/brickllm/graphs/abstract_graph.py index c9ef276..9268dec 100644 --- a/brickllm/graphs/abstract_graph.py +++ b/brickllm/graphs/abstract_graph.py @@ -1,12 +1,13 @@ import os from abc import ABC, abstractmethod -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Tuple, Union from langchain.chat_models.base import BaseChatModel from langgraph.graph import StateGraph from PIL import Image from ..helpers.llm_models import _get_model +from ..utils import ttl_to_building_prompt class AbstractBrickSchemaGraph(ABC): @@ -17,6 +18,8 @@ def __init__(self, model: Union[str, BaseChatModel] = "openai"): self.config = {"configurable": {"thread_id": "1", "llm_model": self.model}} self.result = None self.ttl_output = None + self.generated_building_description = None + self.generated_key_elements = None @abstractmethod def build_graph(self): @@ -81,3 +84,11 @@ def save_ttl_output(self, output_file: str = "brick_schema_output.ttl") -> None: with open(output_file, "w") as f: f.write(self.ttl_output) + + def ttl_to_building_description(self) -> Tuple[str, List[str]]: + if self.ttl_output is None: + raise ValueError("No TTL output found. Please run the graph first.") + self.generated_building_description, self.generated_key_elements = ( + ttl_to_building_prompt(self.ttl_output, self.model) + ) + return self.generated_building_description, self.generated_key_elements diff --git a/brickllm/helpers/__init__.py b/brickllm/helpers/__init__.py index 5ab8e7d..12ec76c 100644 --- a/brickllm/helpers/__init__.py +++ b/brickllm/helpers/__init__.py @@ -6,6 +6,7 @@ prompt_template_local, schema_to_ttl_instructions, ttl_example, + ttl_to_user_prompt, ) __all__ = [ @@ -16,4 +17,5 @@ "schema_to_ttl_instructions", "ttl_example", "prompt_template_local", + "ttl_to_user_prompt", ] diff --git a/brickllm/helpers/prompts.py b/brickllm/helpers/prompts.py index 11a0bf5..98125a3 100644 --- a/brickllm/helpers/prompts.py +++ b/brickllm/helpers/prompts.py @@ -9,7 +9,7 @@ You are now asked to identify the elements presents in the user prompt, even if not explicitly mentioned.\n USER PROMPT: {prompt} \n ELEMENTS: {elements_dict} \n - """ + """ # noqa get_elem_children_instructions: str = """ You are a BrickSchema ontology expert and you are provided with a user prompt which describes a building or facility.\n @@ -22,7 +22,7 @@ USER PROMPT: {prompt} \n ELEMENTS HIERARCHY: {elements_list} \n - """ + """ # noqa get_relationships_instructions: str = """ You are a BrickSchema ontology expert and are provided with a detailed description of a building or facility.\n @@ -35,7 +35,7 @@ If an element has no relationships, add an empty string in place of the missing component ("Room.1","").\n Hierarchical structure: {building_structure}\n USER PROMPT: {prompt} -""" +""" # noqa ttl_example: str = """ @prefix bldg: . @@ -84,7 +84,7 @@ bldg:livingroom a brick:Room ; brick:isPartOf bldg:Milano_Residence_1 . -""" +""" # noqa schema_to_ttl_instructions: str = """ You are a BrickSchema ontology expert and you are provided with a user prompt which describes a building or facility.\n @@ -102,7 +102,23 @@ USER DESCRIPTION: {prompt}\n COMPONENTS DICT: {sensors_dict}\n -""" +""" # noqa + +ttl_to_user_prompt: str = """ + You are a BrickSchema ontology expert tasked with generating a clear and concise description of a building or facility from a TTL script. + + Your output must follow these guidelines: + - Focus on the key building characteristics, components and relationships present in the TTL + - Maintain technical accuracy and use proper Brick terminology + - Keep descriptions clear and well-structured + - Only include information explicitly stated in the TTL script + - If no TTL content is provided, return an empty string + + TTL script to analyze: + + {ttl_script} + +""" # noqa prompt_template_local: str = """ Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. @@ -113,4 +129,4 @@ {user_prompt} ### Response: -""" +""" # noqa diff --git a/brickllm/schemas.py b/brickllm/schemas.py index dd61887..5ba06b4 100644 --- a/brickllm/schemas.py +++ b/brickllm/schemas.py @@ -16,3 +16,12 @@ class TTLSchema(BaseModel): ttl_output: str = Field( ..., description="The generated BrickSchema turtle/rdf script." ) + + +class TTLToBuildingPromptSchema(BaseModel): + building_description: str = Field( + ..., description="The generated building description." + ) + key_elements: List[str] = Field( + ..., description="The generated list of key elements." + ) diff --git a/brickllm/utils/__init__.py b/brickllm/utils/__init__.py index 5524b11..a7bf289 100644 --- a/brickllm/utils/__init__.py +++ b/brickllm/utils/__init__.py @@ -22,6 +22,7 @@ validate_ttl, ) from .rdf_parser import extract_rdf_graph +from .ttl_to_prompt import ttl_to_building_prompt __all__ = [ "find_parents", @@ -44,4 +45,5 @@ "general_query", "validate_ttl", "extract_rdf_graph", + "ttl_to_building_prompt", ] diff --git a/brickllm/utils/ttl_to_prompt.py b/brickllm/utils/ttl_to_prompt.py new file mode 100644 index 0000000..115e280 --- /dev/null +++ b/brickllm/utils/ttl_to_prompt.py @@ -0,0 +1,27 @@ +from typing import List, Tuple, Union + +from langchain.chat_models.base import BaseChatModel +from langchain_community.llms import Ollama +from langchain_core.messages import HumanMessage, SystemMessage + +from ..helpers import ttl_to_user_prompt +from ..schemas import TTLToBuildingPromptSchema + + +def ttl_to_building_prompt( + ttl_file: str, llm: Union[Ollama, BaseChatModel] +) -> Tuple[str, List[str]]: + + # Enforce structured output + structured_llm = llm.with_structured_output(TTLToBuildingPromptSchema) + + # System message + system_message = ttl_to_user_prompt.format(ttl_script=ttl_file) + + # Generate question + answer = structured_llm.invoke( + [SystemMessage(content=system_message)] + + [HumanMessage(content="Generate the TTL.")] + ) + + return answer.building_description, answer.key_elements diff --git a/examples/example_custom_llm.py b/examples/example_custom_llm.py index b548c58..6fa0231 100644 --- a/examples/example_custom_llm.py +++ b/examples/example_custom_llm.py @@ -34,3 +34,12 @@ # save the result to a file brick_graph.save_ttl_output("my_building_custom.ttl") + +# Generate the building description from the generated ttl file +building_description, key_elements = brick_graph.ttl_to_building_description() + +print("Generated building description:") +print(building_description) +print("--------------------------------") +print("Generated key elements:") +print(key_elements) diff --git a/examples/example_openai.py b/examples/example_openai.py index 9d8107d..d70c0b9 100644 --- a/examples/example_openai.py +++ b/examples/example_openai.py @@ -32,3 +32,12 @@ # save the result to a file brick_graph.save_ttl_output("my_building.ttl") + +# Generate the building description from the generated ttl file +building_description, key_elements = brick_graph.ttl_to_building_description() + +print("Generated building description:") +print(building_description) +print("--------------------------------") +print("Generated key elements:") +print(key_elements) From 3d36efa916ae51a7d6f7fe068e2417c3c42b58e3 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Nov 2024 10:13:03 +0000 Subject: [PATCH 3/7] ci(release): 1.2.0-beta.1 [skip ci] ## [1.2.0-beta.1](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.1.2...v1.2.0-beta.1) (2024-11-11) ### Features * ttl_to_building_description function ([d83e66f](https://github.com/EURAC-EEBgroup/brick-llm/commit/d83e66f5851a4db71825c925389d3183cb10faaf)) ### Docs * imporeved docs and ttl_output method ([24a7d8b](https://github.com/EURAC-EEBgroup/brick-llm/commit/24a7d8ba1d94fa25c0d6c5db33b38853bc2d5ff2)) --- CHANGELOG.md | 12 ++++++++++++ pyproject.toml | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc7bb47..9eb894f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [1.2.0-beta.1](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.1.2...v1.2.0-beta.1) (2024-11-11) + + +### Features + +* ttl_to_building_description function ([d83e66f](https://github.com/EURAC-EEBgroup/brick-llm/commit/d83e66f5851a4db71825c925389d3183cb10faaf)) + + +### Docs + +* imporeved docs and ttl_output method ([24a7d8b](https://github.com/EURAC-EEBgroup/brick-llm/commit/24a7d8ba1d94fa25c0d6c5db33b38853bc2d5ff2)) + ## [1.1.2](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.1.1...v1.1.2) (2024-11-05) diff --git a/pyproject.toml b/pyproject.toml index f9cceeb..15bc8c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "brickllm" -version = "1.1.2" +version = "1.2.0b1" description = "Library for generating RDF files following BrickSchema ontology using LLM" authors = ["Marco Perini ", "Daniele Antonucci "] license = "BSD-3-Clause" From bf4bdaecca779ff835e2349bfcdff7a3d17ead0e Mon Sep 17 00:00:00 2001 From: Marco Perini Date: Mon, 11 Nov 2024 11:38:19 +0100 Subject: [PATCH 4/7] fix: improved ttl description generation --- brickllm/helpers/prompts.py | 5 ++ brickllm/utils/ttl_to_prompt.py | 14 +++- examples/example_ttl_to_description.py | 32 +++++++++ examples/my_building.ttl | 95 ++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 examples/example_ttl_to_description.py create mode 100644 examples/my_building.ttl diff --git a/brickllm/helpers/prompts.py b/brickllm/helpers/prompts.py index 98125a3..158342d 100644 --- a/brickllm/helpers/prompts.py +++ b/brickllm/helpers/prompts.py @@ -114,6 +114,11 @@ - Only include information explicitly stated in the TTL script - If no TTL content is provided, return an empty string + Eventually, the user can provide additional instructions to help you generate the building description. + + {additional_instructions} + + TTL script to analyze: {ttl_script} diff --git a/brickllm/utils/ttl_to_prompt.py b/brickllm/utils/ttl_to_prompt.py index 115e280..5c280c5 100644 --- a/brickllm/utils/ttl_to_prompt.py +++ b/brickllm/utils/ttl_to_prompt.py @@ -1,4 +1,5 @@ -from typing import List, Tuple, Union +import logging +from typing import List, Optional, Tuple, Union from langchain.chat_models.base import BaseChatModel from langchain_community.llms import Ollama @@ -7,17 +8,24 @@ from ..helpers import ttl_to_user_prompt from ..schemas import TTLToBuildingPromptSchema +logger = logging.getLogger(__name__) + def ttl_to_building_prompt( - ttl_file: str, llm: Union[Ollama, BaseChatModel] + ttl_file: str, + llm: Union[Ollama, BaseChatModel], + additional_instructions: Optional[str] = None, ) -> Tuple[str, List[str]]: # Enforce structured output structured_llm = llm.with_structured_output(TTLToBuildingPromptSchema) # System message - system_message = ttl_to_user_prompt.format(ttl_script=ttl_file) + system_message = ttl_to_user_prompt.format( + ttl_script=ttl_file, additional_instructions=additional_instructions + ) + logger.info("Generating building description and key elements from the TTL file.") # Generate question answer = structured_llm.invoke( [SystemMessage(content=system_message)] diff --git a/examples/example_ttl_to_description.py b/examples/example_ttl_to_description.py new file mode 100644 index 0000000..8e40767 --- /dev/null +++ b/examples/example_ttl_to_description.py @@ -0,0 +1,32 @@ +import os + +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +from brickllm.utils import ttl_to_building_prompt + +# Load environment variables +load_dotenv() + +# Create a custom model +custom_model = ChatOpenAI(temperature=0.8, model="gpt-4o") + +current_dir = os.path.dirname(os.path.abspath(__file__)) +file_name = "my_building.ttl" + +# Open the ttl file +with open(os.path.join(current_dir, file_name), "r") as file: + ttl_file = file.read() + +# Generate the building description from the ttl file +building_description, key_elements = ttl_to_building_prompt( + ttl_file, + custom_model, + additional_instructions="Keep a professional and structured tone.", +) + +print("Generated building description:") +print(building_description) +print("--------------------------------") +print("Generated key elements:") +print(key_elements) diff --git a/examples/my_building.ttl b/examples/my_building.ttl new file mode 100644 index 0000000..e3497bb --- /dev/null +++ b/examples/my_building.ttl @@ -0,0 +1,95 @@ +@prefix bldg: . +@prefix brick: . + +bldg:Bolzano_Building a brick:Building ; + brick:hasLocation [ brick:value "Bolzano" ] . + +bldg:Floor_1 a brick:Floor ; + brick:isPartOf bldg:Bolzano_Building . + +bldg:Floor_2 a brick:Floor ; + brick:isPartOf bldg:Bolzano_Building . + +bldg:Floor_3 a brick:Floor ; + brick:isPartOf bldg:Bolzano_Building . + +bldg:Office_1 a brick:Office ; + brick:isPartOf bldg:Floor_1 . + +bldg:Office_2 a brick:Office ; + brick:isPartOf bldg:Floor_2 . + +bldg:Office_3 a brick:Office ; + brick:isPartOf bldg:Floor_3 . + +bldg:Room_1 a brick:Room ; + brick:isPartOf bldg:Office_1 . + +bldg:Room_2 a brick:Room ; + brick:isPartOf bldg:Office_1 . + +bldg:Room_3 a brick:Room ; + brick:isPartOf bldg:Office_2 . + +bldg:Room_4 a brick:Room ; + brick:isPartOf bldg:Office_2 . + +bldg:Room_5 a brick:Room ; + brick:isPartOf bldg:Office_3 . + +bldg:Room_6 a brick:Room ; + brick:isPartOf bldg:Office_3 . + +bldg:Temperature_Sensor_1 a brick:Temperature_Sensor ; + brick:isPointOf bldg:Room_1 . + +bldg:Humidity_Sensor_1 a brick:Humidity_Sensor ; + brick:isPointOf bldg:Room_1 . + +bldg:CO_Sensor_1 a brick:CO_Sensor ; + brick:isPointOf bldg:Room_1 . + +bldg:Temperature_Sensor_2 a brick:Temperature_Sensor ; + brick:isPointOf bldg:Room_2 . + +bldg:Humidity_Sensor_2 a brick:Humidity_Sensor ; + brick:isPointOf bldg:Room_2 . + +bldg:CO_Sensor_2 a brick:CO_Sensor ; + brick:isPointOf bldg:Room_2 . + +bldg:Temperature_Sensor_3 a brick:Temperature_Sensor ; + brick:isPointOf bldg:Room_3 . + +bldg:Humidity_Sensor_3 a brick:Humidity_Sensor ; + brick:isPointOf bldg:Room_3 . + +bldg:CO_Sensor_3 a brick:CO_Sensor ; + brick:isPointOf bldg:Room_3 . + +bldg:Temperature_Sensor_4 a brick:Temperature_Sensor ; + brick:isPointOf bldg:Room_4 . + +bldg:Humidity_Sensor_4 a brick:Humidity_Sensor ; + brick:isPointOf bldg:Room_4 . + +bldg:CO_Sensor_4 a brick:CO_Sensor ; + brick:isPointOf bldg:Room_4 . + +bldg:Temperature_Sensor_5 a brick:Temperature_Sensor ; + brick:isPointOf bldg:Room_5 . + +bldg:Humidity_Sensor_5 a brick:Humidity_Sensor ; + brick:isPointOf bldg:Room_5 . + +bldg:CO_Sensor_5 a brick:CO_Sensor ; + brick:isPointOf bldg:Room_5 . + +bldg:Temperature_Sensor_6 a brick:Temperature_Sensor ; + brick:isPointOf bldg:Room_6 . + +bldg:Humidity_Sensor_6 a brick:Humidity_Sensor ; + brick:isPointOf bldg:Room_6 . + +bldg:CO_Sensor_6 a brick:CO_Sensor ; + brick:isPointOf bldg:Room_6 . From 67115f039ae0a828de5d03e27cfc6c8f329dce79 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Nov 2024 10:41:33 +0000 Subject: [PATCH 5/7] ci(release): 1.2.0-beta.2 [skip ci] ## [1.2.0-beta.2](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.2.0-beta.1...v1.2.0-beta.2) (2024-11-11) ### Bug Fixes * improved ttl description generation ([bf4bdae](https://github.com/EURAC-EEBgroup/brick-llm/commit/bf4bdaecca779ff835e2349bfcdff7a3d17ead0e)) --- CHANGELOG.md | 7 +++++++ pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb894f..79a7645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.2.0-beta.2](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.2.0-beta.1...v1.2.0-beta.2) (2024-11-11) + + +### Bug Fixes + +* improved ttl description generation ([bf4bdae](https://github.com/EURAC-EEBgroup/brick-llm/commit/bf4bdaecca779ff835e2349bfcdff7a3d17ead0e)) + ## [1.2.0-beta.1](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.1.2...v1.2.0-beta.1) (2024-11-11) diff --git a/pyproject.toml b/pyproject.toml index 15bc8c5..3b16607 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "brickllm" -version = "1.2.0b1" +version = "1.2.0b2" description = "Library for generating RDF files following BrickSchema ontology using LLM" authors = ["Marco Perini ", "Daniele Antonucci "] license = "BSD-3-Clause" From 82bead23929a23998f4d7504f31d83bf253927bf Mon Sep 17 00:00:00 2001 From: Marco Perini Date: Mon, 11 Nov 2024 12:25:50 +0100 Subject: [PATCH 6/7] perf: add custom logging level --- brickllm/__init__.py | 2 ++ brickllm/logger.py | 38 +++++++++++++++++++++++++++++ brickllm/nodes/generation_local.py | 3 ++- brickllm/nodes/get_elem_children.py | 5 +++- brickllm/nodes/get_elements.py | 3 ++- brickllm/nodes/get_relationships.py | 3 ++- brickllm/nodes/get_sensors.py | 3 ++- brickllm/nodes/schema_to_ttl.py | 3 ++- brickllm/nodes/validate_schema.py | 3 ++- 9 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 brickllm/logger.py diff --git a/brickllm/__init__.py b/brickllm/__init__.py index 1a4e70a..748d6b9 100644 --- a/brickllm/__init__.py +++ b/brickllm/__init__.py @@ -1,4 +1,5 @@ from .configs import GraphConfig +from .logger import custom_logger from .schemas import ( ElemListSchema, RelationshipsSchema, @@ -15,4 +16,5 @@ "State", "StateLocal", "GraphConfig", + "custom_logger", ] diff --git a/brickllm/logger.py b/brickllm/logger.py new file mode 100644 index 0000000..dc93b86 --- /dev/null +++ b/brickllm/logger.py @@ -0,0 +1,38 @@ +import logging + +# Create custom log level +EURAC_LEVEL = 25 +logging.addLevelName(EURAC_LEVEL, "EURAC") + + +def eurac(self, message, *args, **kwargs): + """ + Log with custom EURAC level + """ + if self.isEnabledFor(EURAC_LEVEL): + self._log(EURAC_LEVEL, message, args, **kwargs) + + +# Add eurac method to Logger class +logging.Logger.eurac = eurac + + +# Create and configure logger +def get_logger(name="BrickLLM"): + logger = logging.getLogger(name) + + # Create handler if none exists + if not logger.handlers: + handler = logging.StreamHandler() + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) + handler.setFormatter(formatter) + logger.addHandler(handler) + + logger.setLevel(EURAC_LEVEL) + return logger + + +# Create default logger instance +custom_logger = get_logger() diff --git a/brickllm/nodes/generation_local.py b/brickllm/nodes/generation_local.py index 3c3d089..7a8a8e4 100644 --- a/brickllm/nodes/generation_local.py +++ b/brickllm/nodes/generation_local.py @@ -2,6 +2,7 @@ from .. import StateLocal from ..helpers import prompt_template_local +from ..logger import custom_logger from ..utils import extract_rdf_graph @@ -17,7 +18,7 @@ def generation_local(state: StateLocal, config: Dict[str, Any]) -> Dict[str, Any dict: A dictionary containing the output generated. """ - print("---One shot generation with local LLM Node---") + custom_logger.eurac("🤖 Starting one shot generation with local LLM") instructions = state["instructions"] user_prompt = state["user_prompt"] diff --git a/brickllm/nodes/get_elem_children.py b/brickllm/nodes/get_elem_children.py index 0c8c70b..bc383b4 100644 --- a/brickllm/nodes/get_elem_children.py +++ b/brickllm/nodes/get_elem_children.py @@ -4,6 +4,7 @@ from .. import ElemListSchema, State from ..helpers import get_elem_children_instructions +from ..logger import custom_logger from ..utils import create_hierarchical_dict, filter_elements, get_children_hierarchy @@ -18,7 +19,9 @@ def get_elem_children(state: State, config: Dict[str, Any]) -> Dict[str, Any]: Returns: dict: A dictionary containing the hierarchical structure of identified elements. """ - print("---Get Elem Children Node---") + custom_logger.eurac( + "📊 Getting children for each BrickSchema category in the element list" + ) user_prompt = state["user_prompt"] categories = state["elem_list"] diff --git a/brickllm/nodes/get_elements.py b/brickllm/nodes/get_elements.py index beb32d0..fc33b30 100644 --- a/brickllm/nodes/get_elements.py +++ b/brickllm/nodes/get_elements.py @@ -4,6 +4,7 @@ from .. import ElemListSchema, State from ..helpers import get_elem_instructions +from ..logger import custom_logger from ..utils import get_brick_definition, get_hierarchical_info @@ -19,7 +20,7 @@ def get_elements(state: State, config: Dict[str, Any]) -> Dict[str, Any]: Returns: dict: A dictionary containing the list of identified elements. """ - print("---Get Elements Node---") + custom_logger.eurac("🔍 Getting elements from user prompt") user_prompt = state["user_prompt"] diff --git a/brickllm/nodes/get_relationships.py b/brickllm/nodes/get_relationships.py index 81eb08b..70fb157 100644 --- a/brickllm/nodes/get_relationships.py +++ b/brickllm/nodes/get_relationships.py @@ -6,6 +6,7 @@ from .. import RelationshipsSchema, State from ..helpers import get_relationships_instructions +from ..logger import custom_logger from ..utils import build_hierarchy, find_sensor_paths @@ -20,7 +21,7 @@ def get_relationships(state: State, config: Dict[str, Any]) -> Dict[str, Any]: Returns: dict: A dictionary containing the grouped sensor paths. """ - print("---Get Relationships Node---") + custom_logger.eurac("🔗 Getting relationships between building components") user_prompt = state["user_prompt"] building_structure = state["elem_hierarchy"] diff --git a/brickllm/nodes/get_sensors.py b/brickllm/nodes/get_sensors.py index 0a386a4..ac6c207 100644 --- a/brickllm/nodes/get_sensors.py +++ b/brickllm/nodes/get_sensors.py @@ -1,6 +1,7 @@ from typing import Any, Dict from .. import State +from ..logger import custom_logger def get_sensors(state: State) -> Dict[str, Any]: @@ -13,7 +14,7 @@ def get_sensors(state: State) -> Dict[str, Any]: Returns: dict: A dictionary containing sensor UUIDs mapped to their locations. """ - print("---Get Sensor Node---") + custom_logger.eurac("📡 Getting sensors information") uuid_dict = { "Building#1>Floor#1>Office#1>Room#1": [ diff --git a/brickllm/nodes/schema_to_ttl.py b/brickllm/nodes/schema_to_ttl.py index 741a3e4..f9486b1 100644 --- a/brickllm/nodes/schema_to_ttl.py +++ b/brickllm/nodes/schema_to_ttl.py @@ -5,6 +5,7 @@ from .. import State, TTLSchema from ..helpers import schema_to_ttl_instructions, ttl_example +from ..logger import custom_logger def schema_to_ttl(state: State, config: Dict[str, Any]) -> Dict[str, Any]: @@ -18,7 +19,7 @@ def schema_to_ttl(state: State, config: Dict[str, Any]) -> Dict[str, Any]: Returns: dict: A dictionary containing the generated TTL output. """ - print("---Schema To TTL Node---") + custom_logger.eurac("📝 Generating TTL from schema") user_prompt = state["user_prompt"] sensors_dict = state["sensors_dict"] diff --git a/brickllm/nodes/validate_schema.py b/brickllm/nodes/validate_schema.py index 913f1d8..76d91d0 100644 --- a/brickllm/nodes/validate_schema.py +++ b/brickllm/nodes/validate_schema.py @@ -1,5 +1,6 @@ from typing import Any, Dict +from ..logger import custom_logger from ..utils import validate_ttl @@ -13,7 +14,7 @@ def validate_schema(state) -> Dict[str, Any]: Returns: dict: A dictionary containing the validation status and report. """ - print("---Validate Schema Node---") + custom_logger.eurac("✅ Validating TTL schema") ttl_output = state.get("ttl_output", None) max_iter = state.get("validation_max_iter", 2) From a7d911207eef70c7324b9448706fa12584654c25 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Nov 2024 11:28:59 +0000 Subject: [PATCH 7/7] ci(release): 1.2.0-beta.3 [skip ci] ## [1.2.0-beta.3](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.2.0-beta.2...v1.2.0-beta.3) (2024-11-11) ### Perf * add custom logging level ([82bead2](https://github.com/EURAC-EEBgroup/brick-llm/commit/82bead23929a23998f4d7504f31d83bf253927bf)) --- CHANGELOG.md | 7 +++++++ pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a7645..2d03f0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.2.0-beta.3](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.2.0-beta.2...v1.2.0-beta.3) (2024-11-11) + + +### Perf + +* add custom logging level ([82bead2](https://github.com/EURAC-EEBgroup/brick-llm/commit/82bead23929a23998f4d7504f31d83bf253927bf)) + ## [1.2.0-beta.2](https://github.com/EURAC-EEBgroup/brick-llm/compare/v1.2.0-beta.1...v1.2.0-beta.2) (2024-11-11) diff --git a/pyproject.toml b/pyproject.toml index 3b16607..5389cd2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "brickllm" -version = "1.2.0b2" +version = "1.2.0b3" description = "Library for generating RDF files following BrickSchema ontology using LLM" authors = ["Marco Perini ", "Daniele Antonucci "] license = "BSD-3-Clause"