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

Pipeline: Add pipeline subsystem #60

Merged
merged 23 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b18b16e
Add pipeline base class and a simple pipeline
kaancayli Feb 15, 2024
46c09a5
Run black formatter
kaancayli Feb 15, 2024
8cde996
Rename base pipeline
kaancayli Feb 15, 2024
95e767a
Address feedbacks
kaancayli Feb 15, 2024
c24439c
Merge branch 'main' into feature/pipeline-subsystem-v1
kaancayli Feb 19, 2024
dbb189f
Fix syntax errors
kaancayli Feb 19, 2024
04566a4
Add tutor chat and summary pipelines
kaancayli Feb 19, 2024
93bc858
Remove unused imports
kaancayli Feb 19, 2024
d7355b4
Generalize pipeline superclass
MichaelOwenDyer Feb 19, 2024
741b14f
Merge commit
MichaelOwenDyer Feb 19, 2024
44ac136
Fix import errors and filepaths
kaancayli Feb 19, 2024
1feadd1
Merge branch 'main' of github.com:ls1intum/Pyris into feature/pipelin…
kaancayli Feb 19, 2024
6e6839f
Merge branch 'feature/pipeline-subsystem-v1' of github.com:ls1intum/P…
kaancayli Feb 19, 2024
47c49e5
Format file
kaancayli Feb 19, 2024
aba2d25
Naming changes and import bug fixes
kaancayli Feb 19, 2024
1a921e3
Create a singleton abstract metaclass and make pipelines singleton
kaancayli Feb 21, 2024
5b4e55c
Add caching to summary pipeline
kaancayli Feb 21, 2024
bfa3da5
Add repr and str methods
kaancayli Feb 21, 2024
9d82946
Minor adjustments
kaancayli Feb 21, 2024
1c2f107
Remove singleton abstract metaclass for now, since pipelines can use …
kaancayli Feb 21, 2024
588a44b
Address feedbacks
kaancayli Feb 21, 2024
578f9d8
Revert __str__ implementation
kaancayli Feb 21, 2024
12a709b
Uncomment
kaancayli Feb 21, 2024
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
3 changes: 2 additions & 1 deletion app/pipeline/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from pipeline.pipeline import AbstractPipeline
from pipeline.pipeline import Pipeline
from pipeline.chat.simple_chat_pipeline import SimpleChatPipeline
21 changes: 21 additions & 0 deletions app/pipeline/chat/chat_pipeline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from abc import ABC, abstractmethod

from domain import IrisMessage
from pipeline import Pipeline


class ProgrammingExerciseTutorChatPipeline(Pipeline, ABC):
"""
Abstract class for the programming exercise tutor chat pipeline implementations.
This class defines the signature of all implementations of this Iris feature.
"""

def __call__(self, query: IrisMessage, **kwargs) -> IrisMessage:
return self._run(query)

@abstractmethod
def _run(self, query: IrisMessage) -> IrisMessage:
"""
Runs the pipeline and returns the response message.
"""
raise NotImplementedError
15 changes: 6 additions & 9 deletions app/pipeline/chat/simple_chat_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,23 @@

from domain import IrisMessage, IrisMessageRole
from llm.langchain import IrisLangchainChatModel
from pipeline import AbstractPipeline
from pipeline.chat.chat_pipeline import ProgrammingExerciseTutorChatPipeline


class SimpleChatPipeline(AbstractPipeline):
class SimpleChatPipeline(ProgrammingExerciseTutorChatPipeline):
"""A simple chat pipeline that uses our custom langchain chat model for our own request handler"""

llm: IrisLangchainChatModel
pipeline: Runnable

def __init__(self, llm: IrisLangchainChatModel, name=None):
def __init__(self, llm: IrisLangchainChatModel):
self.llm = llm
self.pipeline = {"query": itemgetter("query")} | llm | StrOutputParser()
super().__init__(name=name)
super().__init__(implementation_id="simple_chat_pipeline")

def __call__(self, query: IrisMessage, **kwargs) -> IrisMessage:
def _run(self, query: IrisMessage) -> IrisMessage:
"""
Runs the pipeline and is intended to be called by __call__
:param query: The query
:param kwargs: keyword arguments
:return: IrisMessage
Gets a response from the langchain chat model
"""
if query is None:
raise ValueError("IrisMessage must not be None")
Expand Down
22 changes: 9 additions & 13 deletions app/pipeline/chat/tutor_chat_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@

from domain import IrisMessage, IrisMessageRole
from llm.langchain import IrisLangchainChatModel
from pipeline import AbstractPipeline

from pipeline.chat.chat_pipeline import ProgrammingExerciseTutorChatPipeline

logger = logging.getLogger(__name__)


class TutorChatPipeline(AbstractPipeline):
class TutorChatPipelineReferenceImpl(ProgrammingExerciseTutorChatPipeline):
"""Tutor chat pipeline that answers exercises related questions from students."""

llm: IrisLangchainChatModel
pipeline: Runnable
prompt_str: str
prompt: ChatPromptTemplate

def __init__(self, llm: IrisLangchainChatModel, name=None):
super().__init__(name=name)
def __init__(self, llm: IrisLangchainChatModel):
super().__init__(implementation_id="tutor_chat_pipeline_reference_impl")
# Set the langchain chat model
self.llm = llm
# Load the prompt from a file
Expand All @@ -31,21 +28,20 @@ def __init__(self, llm: IrisLangchainChatModel, name=None):
os.path.join(dirname, "../prompts/iris_tutor_chat_prompt.txt", "r")
) as file:
logger.debug("Loading tutor chat prompt...")
self.prompt_str = file.read()
prompt_str = file.read()
# Create the prompt
self.prompt = ChatPromptTemplate.from_messages(
prompt = ChatPromptTemplate.from_messages(
[
SystemMessagePromptTemplate.from_template(self.prompt_str),
SystemMessagePromptTemplate.from_template(prompt_str),
]
)
# Create the pipeline
self.pipeline = self.prompt | llm | StrOutputParser()
self.pipeline = prompt | llm | StrOutputParser()

def __call__(self, query: IrisMessage, **kwargs) -> IrisMessage:
def _run(self, query: IrisMessage) -> IrisMessage:
"""
Runs the pipeline
:param query: The query
:param kwargs: keyword arguments
:return: IrisMessage
"""
if query is None:
Expand Down
20 changes: 8 additions & 12 deletions app/pipeline/pipeline.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
from abc import ABCMeta, abstractmethod
from abc import ABCMeta

from domain import IrisMessage


class AbstractPipeline(metaclass=ABCMeta):
class Pipeline(metaclass=ABCMeta):
"""Abstract class for all pipelines"""

name: str
implementation_id: str

def __init__(self, name=None):
self.name = name
def __init__(self, implementation_id=None):
self.implementation_id = implementation_id

@abstractmethod
def __call__(self, **kwargs) -> IrisMessage:
def __call__(self, **kwargs):
"""
kaancayli marked this conversation as resolved.
Show resolved Hide resolved
Runs the pipeline and is intended to be called by __call__
:param kwargs: keyword arguments
:return: IrisMessage
Extracts the required parameters from the kwargs runs the pipeline.
"""
raise NotImplementedError

Loading