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

Add ChatAuto #38

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

mconflitti-pbc
Copy link

Issue #37

Simple abstraction to enable ability to swap providers and Chat args through environment variables.

Example use case:

  • Content deployed to Connect uses Chatlas
  • Publisher wants to modify settings or use a different model entirely
  • Update env var values and save to restart app

Caveats:

  • still requires deps to be installed for various providers
  • the chat arg settings through env var could be added to the Chat base class rather than this wrapper if deemed necessary



def ChatAuto(
provider: Optional[str] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice if this provided typing support for available options (perhaps via Literal)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Tried out an enum at one point as well. Didn't seem to make sense unless that enum becomes the official list used throughout.

List could get long(er than it already is), but something like:

SUPPORTED_PROVIDERS = Literal['openai', 'groq', ...]

def ChatAuto(
    provider: Optional[SUPPORTED_PROVIDERS] = None,

Maybe an official string enum to track all supported Chat models would make sense here. idk. Just want to avoid having too many lists of providers that will need to be updated.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind a bit of repetition if it's straightforward to update -- if there's just a Literal alongside the _provider_chat_model_map with a comment about updating both that seems good enough?

chat_fun = ChatAuto
assert_turns_system(chat_fun)
assert_turns_existing(chat_fun)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to have another test that fails of _provider_chat_model_map (or something like it) doesn't hold every Chat*() implementation. I just know I'll be adding Chat*() classes and will definitely forget to add ChatAuto() support.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea! Is there a place now that holds the official list of all Chat funcs? Would be great to centralize that if possible.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I was thinking we'd just compare _provider_chat_model_map to dir(chatlas), grepping for anything that starts with ^Chat*

"Provider name is required as parameter or `CHATLAS_CHAT_PROVIDER` must be set."
)

kwargs |= dict(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elsewhere in the codebase I use {**x, **y} to accumulate kwargs in situations like this, so I'd prefer it here as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can make sure this follows suit! Though I am also willing to go update those occurrences to utilize this operator :)

Copy link
Collaborator

@cpsievert cpsievert Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the link to the PEP. I don't feel super strongly either way, but I'm inclined to keep using {**x} since it feels more language-agnostic (i.e., less Python specific)

Comment on lines +121 to +124
if provider not in _provider_chat_model_map:
raise ValueError(
"Provider name is required as parameter or `CHATLAS_CHAT_PROVIDER` must be set."
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a different error when provider is None vs a (mis-specified) string

Comment on lines +116 to +117
ValueError
If no valid provider is specified either through parameters or environment variables.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ValueError
If no valid provider is specified either through parameters or environment variables.
ValueError
If no valid provider is specified either through parameters or environment variables.

Comment on lines +111 to +112
Chat
A configured Chat instance for the specified provider.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Chat
A configured Chat instance for the specified provider.
Chat
A configured Chat instance for the specified provider.

**kwargs,
) -> Chat:
"""
Factory function to create a Chat instance based on a provider specified in code or in an environment variable.
Copy link
Collaborator

@cpsievert cpsievert Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't factory function is the right term here

Suggested change
Factory function to create a Chat instance based on a provider specified in code or in an environment variable.
Create a Chat instance using a provider determined by environment variables.

"""
Factory function to create a Chat instance based on a provider specified in code or in an environment variable.

This function creates a Chat instance based on the specified provider, with optional system prompt and conversation turns.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This function creates a Chat instance based on the specified provider, with optional system prompt and conversation turns.
Create a Chat instance based on the specified provider, with optional system prompt and conversation turns.

The provider can be specified either through the function parameter or via the CHATLAS_CHAT_PROVIDER environment variable.
Additional configuration can be provided through kwargs or the CHATLAS_CHAT_ARGS environment variable (as JSON). This allows
you to easily switch between different chat providers by changing the environment variable without modifying your code.

Copy link
Collaborator

@cpsievert cpsievert Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here would be a good place to explain environment variables will win over kwargs (and the other args)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants