Panel 1.3.0 Release
What is Panel?
Panel is an open-source Python library that lets you easily build powerful tools, dashboards and complex applications entirely in Python. It has a batteries-included philosophy, putting the PyData ecosystem, powerful data tables and much more at your fingertips. High-level reactive APIs and lower-level callback based APIs ensure you can quickly build exploratory applications, but you aren’t limited if you build complex, multi-page apps with rich interactivity. Panel is a member of the HoloViz ecosystem, your gateway into a connected ecosystem of data exploration tools.
New release!
We are very pleased to announce the 1.3.0 release of Panel! This release packs many exciting new features, specifically:
- A new
panel.chat
subpackage containing components with powerful capabilities for interacting with LLM whether local or remote. - Compatibility with Param 2.0 bringing powerful new features including the ability to leverage reactive expressions using the
rx
wrapper and deeper support for reactively linking parameters, expressions and bound functions on Panel components.
Special thanks to our first time contributors @aktech, @meson800 and @monodera and returning contributors @cdeil, @pierrotsmnrd and @TheoMartin. We also want to highlight the contribution of our new core contributor @ahuang11 for developing the chat components and recognize @MarcSkovMadsen and @philippjfr for their efforts on testing and improving these new components. Finally we thank the entire core team including @sophiamyang, @Hoxbro, @MarcSkovMadsen, @maximlt, @ahuang11 and @philippjfr for their continued efforts.
If you are using Anaconda, you can get latest Panel with conda install panel
, and using pip you can install it with pip install panel
.
Chat Components
With the huge amount of popularity of LLMs it is way overdue for Panel to add components that make it easy to interact with them. See the following trailer as a quick introduction:
and find a variety of examples demonstrating the cabilities of these new features at Panel Chat Examples page, including examples using LangChain, OpenAI, Mistral, Llama, and RAG.
In Panel we want to focus on building general components that let you achieve what you need but also provide the flexibility to compose components as needed. Therefore the panel.chat
subpackage consists of a number of components which are composable incudling the:
These components build on each other as shown in the diagram below:
At the core is a ChatMessage
which can encapsulate any other output and associates this with a user, a timestamp and reaction icons:
= pn.chat.ChatMessage('When did Panel add support for Chat components?', user='User')
msg
msg
The ChatFeed
adds support for composing multiple ChatMessage
s and a simply API for send
ing new messages:
= pn.chat.ChatFeed(msg)
feed
'Chat components were added in v1.3.0!', user='Developer', avatar='👩')
feed.send(
feed
Lastly the ChatInterface
extends the ChatFeed
by adding a UI for interacting with the ChatFeed
:
*feed, width=600) pn.chat.ChatInterface(
Finally we have added basic support for integrating with LangChain via the PanelCallbackHandler
, which we hope will eventually be merged into Langchain itself (if you’re a Langchain dev, call us 😊).
Reactive Expressions & References
Panel 1.3.0 now requires Param 2.0 which we are releasing simultaneously. Not only does the new Param release clean up the namespace of all Panel objects but it also adds support for two major new capabilities:
- Allow passing parameters, widgets, expressions and bound functions as references to Panel components
- Integrating support for reactive expressions using the
param.rx
API
To unpack this a little bit let’s play around with rx
a little bit:
= pn.widgets.IntSlider(start=0, end=7, value=3)
slider
** 2 slider.rx()
This very simple example demonstrates the core idea behind reactive expressions. It allows you to treat a dynamic reference, e.g. a widget value, as if it was the actual object, in this case an int
. This allows you to build reactive pipelines using natural syntax. To discover more about reactive expressions, see the Param documentation.
Of course this extends well beyond this simple example and when combined with the ability for Panel components to resolve references makes it possible to write complex interactive components using natural syntax:
= pn.widgets.Select(name='Pick a dataset', options={
dataset 'penguins': 'https://datasets.holoviz.org/penguins/v1/penguins.csv',
'stocks': 'https://datasets.holoviz.org/stocks/v1/stocks.csv'
})= pn.widgets.IntSlider(value=5, start=0, end=20, name='N rows')
nrows
# Load the currently selected dataset and sample nrows from it
= pn.bind(pd.read_csv, dataset).rx().sample(n=nrows)
df
# Bind the current value of the `df` expression to the Tabulator widget
= pn.widgets.Tabulator(df, page_size=5, pagination='remote')
table
pn.Row(pn.Column(dataset, nrows), table)
Using pn.bind
we can dynamically load various datasets and then apply transformations by turning the result into a reactive expression, e.g. to sample a variable number of rows from the dataset. Lastly we can pass the resulting reactive expression to Tabulator
which will automatically reflect the result of the expression.
Not only can Panel now resolve such expressions but it can even resolve references nested inside another object:
= pn.widgets.FloatSlider(start=6, end=24, value=12, name='Font Size')
font_size = pn.widgets.ColorPicker(name='Color')
color
pn.Row(
pn.Column(font_size, color),'Hello World!', styles={'color': color, 'font-size': pn.rx('{}pt').format(font_size)})
pn.pane.HTML( )
Enhancements & Components
OAuth improvements
Panel has shipped with OAuth integration for a very long time. In this release we finally spent some time rationalizing the code and adding support for:
- Authorization code and password based OAuth grant workflows for when you don’t want to issue a client secret for your Panel application
- Adding the ability to automatically refresh
access_token
s whenever they expire using the--oauth-refresh-tokens
(discover more here)
Colormap Widget
The new ColorMap
widget makes it easy to let users pick between multiple color palettes.
from matplotlib.cm import Reds, Greens, Blues, viridis
= {'Reds': Reds, 'Greens': Greens, 'Blues': Blues, 'viridis': viridis}
cmaps
=cmaps, ncols=2) pn.widgets.ColorMap(options
Changelog
Feature
Enhancement
- Add unit to widget in
HoloViews
pane if provided (#5535) - Allow registering global
on_session_destroyed
callback (#5585) - Implement
auto_grow
onTextAreaInput
(#5592) - Add ability to redirect users from authorization callback (#5594)
- Add support for
Path
object inFileDownload
(#5607) - Add authorization_code and password based OAuth login handlers (#5547)
- Add format to
EditableFloatSlider
andEditableIntSlider
(#5631) - Add support for decorating async functions with
pn.io.cache
(#5649) - Map
param.Bytes
toFileInput
widget (#5665)
Bug fixes
- Fixes for
Column
invisiblescroll_button
taking space (#5532) - Guard undefined values from being set on
BrowserInfo
(#5588) - Fix thumbnails and use Panel design on index page (#5595)
- Fix regressions in
TextEditor
caused by migration to shadow DOM (#5609) - Sync
location
state from request (#5581) - Fix
Select
widget label offset in Material Design (#5639) - Override token contents when reusing sessions (#5640)
- Fix patching a table with a
DataFrame
with a custom index (#5645) - Set
FloatPanel
status correctly on initialization (#5651) - Fix patching table with
pd.Timestamp
values (#5650) - Ensure
notifications
andbrowser_info
are loaded whenHoloViews
is loaded - Gracefully handle resolution of invalid paths in
_stylesheets
(#5666) - Handle patching tables with
NaT
values (#5675)
Compatibility
- Upgrade to Param 2.0
- Compatibility with Bokeh 3.3.0