Skip to content

Commit

Permalink
release 0.3.4
Browse files Browse the repository at this point in the history
  • Loading branch information
MarchLiu committed Sep 5, 2024
1 parent 3995444 commit 2ee98af
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 60 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ If we want to see the cells role information, could use command `Litchi Show Rol

- Show message's role by prompt

### 0.3.4

- disable toolbar when litchi is waiting response.
- bugs fixed

## About Me

My name is Liu Xin, and my English name is Mars Liu and previously used March Liu. I translated the Python
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jupyter-litchi",
"version": "0.3.2",
"version": "0.3.4",
"description": "litchi is a ai client for jupyter lab",
"keywords": [
"jupyter",
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
long_description = (this_directory / "README.md").read_text()

__import__("setuptools").setup(name="jupyter-litchi",
version="0.3.2",
version="0.3.4",
description="Litchi is a Jupyterlab extension for AI Client",
long_description=long_description,
long_description_content_type='text/markdown',
Expand Down
144 changes: 94 additions & 50 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import { MarkdownCellModel } from '@jupyterlab/cells';
import { INotebookTracker, Notebook } from '@jupyterlab/notebook';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { WidgetExtension } from './toolbar';
// import { ISharedCell } from '@jupyter/ydoc';
import { ICellModel } from '@jupyterlab/cells';
import { DocumentRegistry } from '@jupyterlab/docregistry';
import { Signal } from '@lumino/signaling';
import { Widget } from '@lumino/widgets';

const LITCHI_ID = 'jupyter-litchi:jupyter-litchi';

namespace CommandIDs {
export const CHAT = 'litchi:chat';
export const CLEAN = 'litchi:clean';
export const CONTEXTUAL = 'litchi:contextual';
export const HISTORICAL = 'litchi:historical';
export const TOGGLE_ROLE = 'litchi:show-roles-toggle';
Expand Down Expand Up @@ -51,15 +51,29 @@ export async function activate(
app.commands.addCommand(CommandIDs.CHAT, {
label: 'Litchi Chat',
execute: async () => {
await chatActivate(app, registry, tracker, state, 'chat');
await chatActivate(
app,
registry,
tracker,
state,
widget.isWaiting,
'chat'
);
}
});
palette.addItem({ command: CommandIDs.CHAT, category: 'jupyter-Litchi' });

app.commands.addCommand(CommandIDs.CONTEXTUAL, {
label: 'Litchi Chat Contextual',
execute: async () => {
await chatActivate(app, registry, tracker, state, 'contextual');
await chatActivate(
app,
registry,
tracker,
state,
widget.isWaiting,
'contextual'
);
}
});
palette.addItem({
Expand All @@ -70,7 +84,14 @@ export async function activate(
app.commands.addCommand(CommandIDs.HISTORICAL, {
label: 'Litchi Chat Historical',
execute: async () => {
await chatActivate(app, registry, tracker, state, 'historical');
await chatActivate(
app,
registry,
tracker,
state,
widget.isWaiting,
'historical'
);
}
});
palette.addItem({
Expand All @@ -81,7 +102,14 @@ export async function activate(
app.commands.addCommand(CommandIDs.SELECTED, {
label: 'Litchi Chat Selected',
execute: async () => {
await chatActivate(app, registry, tracker, state, 'selected');
await chatActivate(
app,
registry,
tracker,
state,
widget.isWaiting,
'selected'
);
}
});
palette.addItem({
Expand Down Expand Up @@ -117,60 +145,76 @@ async function chatActivate(
registry: ISettingRegistry,
tracker: INotebookTracker,
state: IStateDB,
waiting: Signal<Widget, boolean>,
subTask: 'chat' | 'contextual' | 'historical' | 'selected'
) {
const cell = tracker.activeCell;
if (cell === null) {
console.error('litchi:chat exit because any cell not been selected');
return;
}
try {
let processing: boolean = false;
waiting.connect((sender, value) => {
processing = value;
});

const notebook = tracker.currentWidget?.content;
if (notebook === undefined) {
console.error('litchi:chat exit because the notebook not found');
return;
}
if (processing) {
console.log('an other process is running');
return;
}

cell.model.sharedModel.setMetadata(LITCHI_MESSAGE_ROLE, 'user');
const content = cell.model.sharedModel.source;
// eslint-disable-next-line eqeqeq
if (content === null) {
console.error('litchi:chat exit because the content of cell is null');
return;
}
const latest = cellToMessage(cell.model);
waiting.emit(true);
const cell = tracker.activeCell;
if (cell === null) {
console.error('litchi:chat exit because any cell not been selected');
return;
}

const model = (await state.fetch('litchi:model'))?.toString();
if (model === null || model === undefined) {
console.error('litchi:chat exit because not any model selected');
return;
}
const notebook = tracker.currentWidget?.content;
if (notebook === undefined) {
console.error('litchi:chat exit because the notebook not found');
return;
}

const settings = await registry.load(LITCHI_ID);
const session: IMessage[] = [
await Message.startUp(settings),
...createContext(subTask, notebook)
];
cell.model.sharedModel.setMetadata(LITCHI_MESSAGE_ROLE, 'user');
const content = cell.model.sharedModel.source;
// eslint-disable-next-line eqeqeq
if (content === null) {
console.error('litchi:chat exit because the content of cell is null');
return;
}
const latest = cellToMessage(cell.model);

const url = settings.get('chat')!.composite!.toString();
const key = settings.get('key')?.composite?.toString();
const model = (await state.fetch('litchi:model'))?.toString();
if (model === null || model === undefined) {
console.error('litchi:chat exit because not any model selected');
return;
}

const message = await chat(url, key, session, latest, model!);
if (message.content && message.content.length > 0) {
const cellModel = new MarkdownCellModel();
cellModel.sharedModel.setSource(message.content);
cellModel.sharedModel.setMetadata(LITCHI_MESSAGE_ROLE, message.role);
}
const settings = await registry.load(LITCHI_ID);
const session: IMessage[] = [
await Message.startUp(settings),
...createContext(subTask, notebook)
];

const { commands } = app;
commands.execute('notebook:insert-cell-below').then(() => {
commands.execute('notebook:change-cell-to-markdown');
});
const url = settings.get('chat')!.composite!.toString();
const key = settings.get('key')?.composite?.toString();

const newCell = notebook.activeCell!;
const newModel = newCell.model.sharedModel;
newModel.setSource(message.content);
newModel.setMetadata(LITCHI_MESSAGE_ROLE, message.role);
const message = await chat(url, key, session, latest, model!);
if (message.content && message.content.length > 0) {
const cellModel = new MarkdownCellModel();
cellModel.sharedModel.setSource(message.content);
cellModel.sharedModel.setMetadata(LITCHI_MESSAGE_ROLE, message.role);
}

const { commands } = app;
commands.execute('notebook:insert-cell-below').then(() => {
commands.execute('notebook:change-cell-to-markdown');
});

const newCell = notebook.activeCell!;
const newModel = newCell.model.sharedModel;
newModel.setSource(message.content);
newModel.setMetadata(LITCHI_MESSAGE_ROLE, message.role);
} finally {
waiting.emit(false);
}
}

function createContext(command: string, notebook: Notebook): IMessage[] {
Expand Down
32 changes: 24 additions & 8 deletions src/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ import { JupyterFrontEnd } from '@jupyterlab/application';

import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { listModels } from './api';
import { Widget } from '@lumino/widgets';
import { Signal, ISignal } from '@lumino/signaling';

function ModelsComponent(props: {
appId: string;
app: JupyterFrontEnd;
registry: ISettingRegistry;
state: IStateDB;
waiting: ISignal<Widget, boolean>;
}) {
// 使用useState来存储模型列表和选中的模型
const [models, setModels] = React.useState<string[]>([]);
const [selectedModel, setSelectedModel] = React.useState<string>('');
const [processing, setProcessing] = React.useState<boolean>(false);

// 使用useEffect来在组件加载时获取模型列表
React.useEffect(() => {
async function loadModels() {
try {
Expand All @@ -42,10 +44,13 @@ function ModelsComponent(props: {
loadModels();
}, []);

// 处理下拉列表选项变化的事件
props.waiting.connect((sender, idle) => {
setProcessing(idle);
});

const handleChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
props.state.save('litchi:model', event.target.value);
setSelectedModel(event.target.value);
await props.state.save('litchi:model', event.target.value);
};

const handleChatClick = async (event: React.MouseEvent) => {
Expand Down Expand Up @@ -78,10 +83,18 @@ function ModelsComponent(props: {
</option>
))}
</select>{' '}
<button onClick={handleChatClick}>Chat</button>{' '}
<button onClick={handleContextualClick}>Contextual</button>{' '}
<button onClick={handleHistoricalClick}>Historical</button>{' '}
<button onClick={handleSelectedClick}>Selected</button>
<button disabled={processing} onClick={handleChatClick}>
Chat
</button>{' '}
<button disabled={processing} onClick={handleContextualClick}>
Contextual
</button>{' '}
<button disabled={processing} onClick={handleHistoricalClick}>
Historical
</button>{' '}
<button disabled={processing} onClick={handleSelectedClick}>
Selected
</button>
</span>
);
}
Expand All @@ -97,6 +110,7 @@ export class WidgetExtension
private readonly app: JupyterFrontEnd;
private readonly registry: ISettingRegistry;
private readonly appId: string;
public readonly isWaiting;

protected render() {
return (
Expand All @@ -105,6 +119,7 @@ export class WidgetExtension
state={this.state}
registry={this.registry}
appId={this.appId}
waiting={this.isWaiting}
/>
);
}
Expand All @@ -120,6 +135,7 @@ export class WidgetExtension
this.app = app;
this.registry = registry;
this.appId = appId;
this.isWaiting = new Signal<Widget, boolean>(this);
}

/**
Expand Down

0 comments on commit 2ee98af

Please sign in to comment.