-
Notifications
You must be signed in to change notification settings - Fork 6
feat: request contextualisation - core functionality #65
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
Open
jcierocki
wants to merge
57
commits into
main
Choose a base branch
from
jc/issue-54-request-context
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 28 commits
Commits
Show all changes
57 commits
Select commit
Hold shift + click to select a range
21506e6
context logic subpackage; type-hint context extraction
a87e8e2
reworked type hint info extraction; extended functionality to also re…
ds-jakub-cierocki 3ad4ecd
hidden args handling enabled
ds-jakub-cierocki b0cc0ae
improved type hints parsing and compatibility using package
ds-jakub-cierocki 4ff5f62
dedicated exceptions for contex-related operations
ds-jakub-cierocki c479c50
useful classmethods for context-related operations
ds-jakub-cierocki e3bb127
make whole context utils module protected; added IQL parsing helper; …
ds-jakub-cierocki de72c7c
parsing type hints _extract_params_and_context() no longer excludes B…
ds-jakub-cierocki d3958c0
adjusted the existing code to be aware of contexts (promts yet untouc…
ds-jakub-cierocki be338bf
adjusted _type_validators.validate_arg_type() to handle typing.Union[]
ds-jakub-cierocki 78f1535
context._utils._does_arg_allow_context() fix
ds-jakub-cierocki 308e2e1
context record is now based on pydantic.BaseModel rather than datacla…
ds-jakub-cierocki 73741d9
type hint lifting
ds-jakub-cierocki 902f5ff
IQL generating LLM prompt passes BaseCallerContext() as filter argume…
ds-jakub-cierocki 6309070
comments cleanup
ds-jakub-cierocki d523bf7
type hint fixes
ds-jakub-cierocki efe212f
Merge branch 'main' (which includes a large refactor by Michal) into …
ds-jakub-cierocki 9ba89e5
post-merge fixes + minor refactor
ds-jakub-cierocki 5fd802f
added missing docstrings; fixed type hints; fixed issues detected by …
ds-jakub-cierocki 09bac55
reworked parse_param_type() function to increase performance, general…
ds-jakub-cierocki d42a369
fix: removed duplicated line from the prompt template
ds-jakub-cierocki c0b0522
adjusted existing unit tests to work with new contextualization logic
ds-jakub-cierocki 9b2e131
linter-recommended fixes
ds-jakub-cierocki 2d0ef4b
contextualization mechanism - dedicated unit tests
ds-jakub-cierocki 6466f61
cleaned up overengineered code remanining from the previous iteration…
ds-jakub-cierocki 637f7fa
replaced pydantic.BaseModel by dataclasses.dataclass, pydantic no lon…
ds-jakub-cierocki f867e25
BaseCallerContext: dataclass w.o. fields -> interface (abstract class…
ds-jakub-cierocki 3423033
LLM now pastes Context() instead of BaseCallerContext() to indicate t…
ds-jakub-cierocki 0d8cd1e
docstring typo fixes; more precise return type hint
ds-jakub-cierocki c97ba15
renamed Context() -> AskerContext(); added more detailed detailed exa…
ds-jakub-cierocki 1294a9c
type hint parsing changes: SomeCustomContext -> AskerContext; Union[a…
ds-jakub-cierocki 999759b
refactor: collection.results.[ViewExecutionResult, ExecutionResult]."…
ds-jakub-cierocki 2e1005a
param type parsing: correctly handling builtins types with args (e.g.…
ds-jakub-cierocki 820066d
type hint fix: explcitly marked BaseCallerContext.alias as typing.Cla…
ds-jakub-cierocki 25fbfa6
docs + benchmarks adjusted to meet new naming [ExecutionResult, ViewE…
ds-jakub-cierocki a154577
redesigned context-not-available error to follow the same principles …
ds-jakub-cierocki 623effd
EXPERIMENTAL: reworked context injection such it is handled immediate…
ds-jakub-cierocki afacf5b
additional unit tests for the new contextualization mechanism
ds-jakub-cierocki dd8b339
context benchmark script and data
ds-jakub-cierocki 6bb0816
refactored main prompt (too long lines), missing end-of-line characters
ds-jakub-cierocki f388f92
better error handling
ds-jakub-cierocki fbecc51
context benchmark dataset fix
ds-jakub-cierocki 5d4ff64
added polars-based accuracy summary to the benchmark
ds-jakub-cierocki e7e8826
adjusted prompt to reduce halucinations: nested filter/context calls …
ds-jakub-cierocki f8bf64e
merged main (inc. new benchmarks + large refactor) -> jc/issue-54-req…
ds-jakub-cierocki c1c871b
merge main
micpst 8eefd9b
fix linters
micpst c28091f
fix tests
micpst 69a8d58
fix tests
micpst d6c8fc6
fix tests
micpst d7026d4
rm old benchmarks
micpst e8271ac
some renames and stuff
micpst bdcc7b3
fix benchmarks
micpst 71f53be
merge main
micpst c82e579
rm chroma file
micpst f5a40cb
add contexts to benchmarks + fix types
micpst fab9d3f
small refactor
micpst File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .context import BaseCallerContext | ||
|
||
__all__ = ["BaseCallerContext"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from inspect import isclass | ||
from typing import Any, Optional, Sequence, Tuple, Type, Union | ||
|
||
import typing_extensions as type_ext | ||
|
||
from dbally.context.context import BaseCallerContext | ||
from dbally.views.exposed_functions import MethodParamWithTyping | ||
|
||
ContextClass: type_ext.TypeAlias = Optional[Type[BaseCallerContext]] | ||
|
||
|
||
def _extract_params_and_context( | ||
filter_method_: type_ext.Callable, hidden_args: Sequence[str] | ||
) -> Tuple[Sequence[MethodParamWithTyping], ContextClass]: | ||
""" | ||
Processes the MethodsBaseView filter method signauture to extract the args and type hints in the desired format. | ||
Context claases are getting excluded the returned MethodParamWithTyping list. Only the first BaseCallerContext | ||
class is returned. | ||
|
||
Args: | ||
filter_method_: MethodsBaseView filter method (annotated with @decorators.view_filter() decorator) | ||
hidden_args: method arguments that should not be extracted | ||
|
||
Returns: | ||
The first field contains the list of arguments, each encapsulated as MethodParamWithTyping. | ||
The 2nd is the BaseCallerContext subclass provided for this filter, or None if no context specified. | ||
""" | ||
|
||
params = [] | ||
context = None | ||
# TODO confirm whether to use typing.get_type_hints(method) or method.__annotations__ | ||
for name_, type_ in type_ext.get_type_hints(filter_method_).items(): | ||
if name_ in hidden_args: | ||
continue | ||
|
||
if isclass(type_) and issubclass(type_, BaseCallerContext): | ||
# this is the case when user provides a context but no other type hint for a specifc arg | ||
context = type_ | ||
type_ = Any | ||
elif type_ext.get_origin(type_) is Union: | ||
union_subtypes = type_ext.get_args(type_) | ||
if not union_subtypes: | ||
type_ = Any | ||
|
||
for subtype_ in union_subtypes: # type: ignore | ||
# TODO add custom error for the situation when user provides more than two contexts for a single filter | ||
# for now we extract only the first context | ||
if isclass(subtype_) and issubclass(subtype_, BaseCallerContext): | ||
if context is None: | ||
context = subtype_ | ||
|
||
params.append(MethodParamWithTyping(name_, type_)) | ||
|
||
return params, context | ||
|
||
|
||
def _does_arg_allow_context(arg: MethodParamWithTyping) -> bool: | ||
""" | ||
Verifies whether a method argument allows contextualization based on the type hints attached to a method signature. | ||
|
||
Args: | ||
arg: MethodParamWithTyping container preserving information about the method argument | ||
|
||
Returns: | ||
Verification result. | ||
""" | ||
|
||
if type_ext.get_origin(arg.type) is not Union and not issubclass(arg.type, BaseCallerContext): | ||
return False | ||
|
||
for subtype in type_ext.get_args(arg.type): | ||
if issubclass(subtype, BaseCallerContext): | ||
return True | ||
|
||
return False |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import ast | ||
from abc import ABC | ||
from typing import Iterable | ||
|
||
from typing_extensions import Self, TypeAlias | ||
|
||
from dbally.context.exceptions import ContextNotAvailableError | ||
|
||
CustomContext: TypeAlias = "BaseCallerContext" | ||
|
||
|
||
class BaseCallerContext(ABC): | ||
""" | ||
An interface for contexts that are used to pass additional knowledge about | ||
the caller environment to the filters. LLM will always return `Context()` | ||
when the context is required and this call will be later substituted by an instance of | ||
a class implementing this interface, selected based on the filter method signature (type hints). | ||
""" | ||
|
||
_alias: str = "Context" | ||
jcierocki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@classmethod | ||
def select_context(cls, contexts: Iterable[CustomContext]) -> Self: | ||
""" | ||
Typically called from a subclass of BaseCallerContext, selects a member object from `contexts` being | ||
an instance of the same class. Effectively provides a type dispatch mechanism, substituting the context | ||
class by its right instance. | ||
|
||
Args: | ||
contexts: A sequence of objects, each being an instance of a different BaseCallerContext subclass. | ||
|
||
Returns: | ||
An instance of the same BaseCallerContext subclass this method is caller from. | ||
|
||
Raises: | ||
ContextNotAvailableError: If the sequence of context objects passed as argument is empty. | ||
""" | ||
|
||
if not contexts: | ||
raise ContextNotAvailableError( | ||
"The LLM detected that the context is required to execute the query +\ | ||
and the filter signature allows contextualization while the context was not provided." | ||
) | ||
|
||
# TODO confirm whether it is possible to design a correct type hints here and skipping `type: ignore` | ||
return next(filter(lambda obj: isinstance(obj, cls), contexts)) # type: ignore | ||
|
||
@classmethod | ||
def is_context_call(cls, node: ast.expr) -> bool: | ||
""" | ||
Verifies whether an AST node indicates context substitution. | ||
|
||
Args: | ||
node: An AST node (expression) to verify: | ||
|
||
Returns: | ||
Verification result. | ||
""" | ||
|
||
return ( | ||
isinstance(node, ast.Call) | ||
and isinstance(node.func, ast.Name) | ||
and node.func.id in [cls._alias, cls.__name__] | ||
) |
micpst marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from abc import ABC | ||
|
||
|
||
class BaseContextException(Exception, ABC): | ||
""" | ||
A base (abstract) exception for all specification context-related exception. | ||
""" | ||
|
||
|
||
class ContextNotAvailableError(Exception): | ||
""" | ||
An exception inheriting from BaseContextException pointining that no sufficient context information | ||
was provided by the user while calling view.ask(). | ||
""" | ||
|
||
|
||
class ContextualisationNotAllowed(Exception): | ||
""" | ||
An exception inheriting from BaseContextException pointining that the filter method signature | ||
does not allow to provide an additional context. | ||
""" | ||
|
||
|
||
# WORKAROUND - traditional inhertiance syntax is not working in context of abstract Exceptions | ||
BaseContextException.register(ContextNotAvailableError) | ||
BaseContextException.register(ContextualisationNotAllowed) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.