-
-
Notifications
You must be signed in to change notification settings - Fork 388
[WIP, MAJOR] Introduce AI persona framework #1324
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
base: main
Are you sure you want to change the base?
Conversation
|
||
def set_local_state_field(self, field: str, value: Any) -> None: | ||
with self.as_custom_client(): | ||
return self.awareness.set_local_state_field(field, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove return
?
f" - Unable to load AI persona from entry point `{persona_ep.name}` due to an exception printed below." | ||
) | ||
self.log.exception(e) | ||
continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
swallowing all the exceptions? Perhaps that's okay, but consider adding inline comment to explain why this is better than failing outright.
def personas(self) -> dict[str, BasePersona]: | ||
return self._personas | ||
|
||
def get_mentioned_personas(self, new_message: Message) -> list[BasePersona]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: docstring
mentioned_persona_names = [persona.name for persona in mentioned_personas] | ||
self.log.info( | ||
f"Received new user message mentioning the following personas: {mentioned_persona_names}." | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional: isn't this a lot of stdout, maybe debug
?
if mentioned_id in self.personas: | ||
persona_list.append(self.personas[mentioned_id]) | ||
|
||
return persona_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: any risk of duplication here?
otherwise you can dedup by using a set to buffer the mentioned_id
or with:
return list(set(persona_list))
Description
This is a major feature PR introduces an AI persona framework to Jupyter AI and allows multiple AI personas to be added per chat. Personas are analogous to "bot accounts" in other chat applications in Slack or Discord.
High-level summary of changes:
"Jupyternaut" has been redefined as a default AI persona provided by Jupyter AI. Jupyternaut will use the same interface as every other AI persona.
This PR changes Jupyternaut to only reply when
@
-mentioned in the chat. All AI personas, including Jupyternaut, will only reply when@
-mentioned. This allows users to precisely control when & which AI personas respond.@
-mention each other to dispatch tasks or use agentic tools only available through another persona.This PR allows other packages to add fully-custom AI personas. Developers can define the name, avatar, and how new messages are handled. Custom AI personas can use any AI model or AI library of their choice, and now have full control over how new messages are handled.
Demo
Screen.Recording.2025-04-13.at.6.10.26.PM.mov
Technical summary
Jupyter AI v2 had a concept of "personas", but these were essentially just names & avatars that could only appear when custom model providers were in use. This caused several issues for developers:
DefaultChatHandler
in Jupyter AI.This PR completely re-defines the concept of a persona in Jupyter AI v3 to address these issues.
Personas are now each defined in a class extending
BasePersona
, an abstract base class provided by Jupyter AI. A summary of the interface is as follows:self.ychat
.self.defaults
.PersonaDefaults
is a Pydantic data model that allows a persona to define its own name and avatar.self.defaults
.self.process_message()
. This is just a plain async function which can do anything. You can define a provider to use any AI model or AI libraries of your choice, as long as they are installed in your Python environment.self.ychat
, e.g.self.ychat.add_message()
.To help orchestrate personas for each chat, this PR also defines a new
PersonaManager
class. A newPersonaManager
is initialized for each newYChat
instance automatically. This class helps initialize the set ofBasePersona
instances for each chat.To allow other packages to install personas, persona classes are loaded from the
"jupyter_ai.personas"
entry point group (EPG) when the server extension starts. Any third-party package can define a persona class and provide it to this EPG to add a custom persona to Jupyter AI.Architecture changes
JupyternautPersona
implementation now fully defines how Jupyternaut handles new messages, supersedingDefaultChatHandler
.Related issues
Other details
jupyter_ai_test
package. That way, others can switch to this branch and test it viajlpm dev-reinstall
.