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

Release/1.1.300 #1041

Merged
merged 4 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

Nothing unreleased!

## [1.1.300rc3] - 2024-05-28

### Added

- Input streaming for tool calls

## [1.1.300rc2] - 2024-05-28

### Added
Expand Down
7 changes: 4 additions & 3 deletions backend/chainlit/emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async def stream_start(self, step_dict: StepDict):
"""Stub method to send a stream start signal to the UI."""
pass

async def send_token(self, id: str, token: str, is_sequence=False):
async def send_token(self, id: str, token: str, is_sequence=False, is_input=False):
"""Stub method to send a message token to the UI."""
pass

Expand Down Expand Up @@ -353,10 +353,11 @@ def stream_start(self, step_dict: StepDict):
step_dict,
)

def send_token(self, id: str, token: str, is_sequence=False):
def send_token(self, id: str, token: str, is_sequence=False, is_input=False):
"""Send a message token to the UI."""
return self.emit(
"stream_token", {"id": id, "token": token, "isSequence": is_sequence}
"stream_token",
{"id": id, "token": token, "isSequence": is_sequence, "isInput": is_input},
)

def set_chat_settings(self, settings: Dict[str, Any]):
Expand Down
18 changes: 12 additions & 6 deletions backend/chainlit/step.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def step(
tags: Optional[List[str]] = None,
disable_feedback: bool = True,
language: Optional[str] = None,
show_input: Union[bool, str] = False,
show_input: Union[bool, str] = "json",
):
"""Step decorator for async and sync functions."""

Expand Down Expand Up @@ -160,7 +160,7 @@ def __init__(
tags: Optional[List[str]] = None,
disable_feedback: bool = True,
language: Optional[str] = None,
show_input: Union[bool, str] = False,
show_input: Union[bool, str] = "json",
):
trace_event(f"init {self.__class__.__name__} {type}")
time.sleep(0.001)
Expand Down Expand Up @@ -356,15 +356,21 @@ async def send(self):

return self

async def stream_token(self, token: str, is_sequence=False):
async def stream_token(self, token: str, is_sequence=False, is_input=False):
"""
Sends a token to the UI.
Once all tokens have been streamed, call .send() to end the stream and persist the step if persistence is enabled.
"""
if is_sequence:
self.output = token
if is_input:
self.input = token
else:
self.output = token
else:
self.output += token
if is_input:
self.input += token
else:
self.output += token

assert self.id

Expand All @@ -377,7 +383,7 @@ async def stream_token(self, token: str, is_sequence=False):
await context.emitter.stream_start(step_dict)
else:
await context.emitter.send_token(
id=self.id, token=token, is_sequence=is_sequence
id=self.id, token=token, is_sequence=is_sequence, is_input=is_input
)

# Handle parameter less decorator
Expand Down
2 changes: 1 addition & 1 deletion backend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "chainlit"
version = "1.1.300rc2"
version = "1.1.300rc3"
keywords = [
'LLM',
'Agents',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/atoms/elements/InlinedElements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const InlinedElements = ({ elements }: Props) => {
);

return (
<Stack gap={1} mt={1}>
<Stack gap={1} mb={2}>
{elementsByType.image?.length ? (
<InlinedImageList items={elementsByType.image} />
) : null}
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/atoms/elements/Plotly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ const _PlotlyElement = ({ element }: Props) => {
layout={state.layout}
frames={state.frames}
config={state.config}
style={{ width: '100%', height: '100%' }}
style={{
width: '100%',
height: '100%',
borderRadius: '1rem',
overflow: 'hidden'
}}
useResizeHandler={true}
/>
</Suspense>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/molecules/messages/ToolCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default function ToolCall({ steps, elements, isRunning }: Props) {
);
}, [steps, isRunning]);

const hasOutput = steps.some((step) => step.output);
const hasOutput = steps.some((step) => step.output || step.input);
const isError = steps.length ? steps[steps.length - 1].isError : false;

if (!steps.length) {
Expand Down Expand Up @@ -102,7 +102,7 @@ export default function ToolCall({ steps, elements, isRunning }: Props) {
}}
>
{steps
.filter((step) => step.output)
.filter((step) => step.output || step.input)
.map((step) => (
<MessageContent
key={step.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const MessageContent = memo(
let lineCount = 0;
let contentLength = 0;

const content =
const outputContent =
message.streaming && message.output
? message.output + CURSOR_PLACEHOLDER
: message.output;
Expand All @@ -41,7 +41,7 @@ const MessageContent = memo(
} = prepareContent({
elements,
id: message.id,
content: content,
content: outputContent,
language: message.language
});

Expand All @@ -61,11 +61,15 @@ const MessageContent = memo(
let inputMarkdown;

if (message.input && message.showInput) {
const inputContent =
message.streaming && message.input
? message.input + CURSOR_PLACEHOLDER
: message.input;
const { preparedContent: input, refElements: inputRefElements } =
prepareContent({
elements,
id: message.id,
content: message.input,
content: inputContent,
language:
typeof message.showInput === 'string'
? message.showInput
Expand Down Expand Up @@ -114,7 +118,7 @@ const MessageContent = memo(
return (
<Stack width="100%" direction="row" className="message-content">
<Box width="100%">
{output ? messageContent : null}
{!!inputMarkdown || output ? messageContent : null}
<InlinedElements elements={outputInlinedElements} />
</Box>
</Stack>
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/components/organisms/chat/dropScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ export default function DropScreen() {
zIndex: 10
}}
>
<Stack alignItems="center" gap={2} color="grey.400">
<ImageIcon sx={{ width: '100px', height: '100px' }} />
<Typography fontWeight={600} fontSize="1.5rem">
<Stack alignItems="center" gap={2}>
<ImageIcon
sx={{ width: '100px', height: '100px', color: 'grey.400' }}
/>
<Typography color="grey.200" fontWeight={600} fontSize="1.5rem">
<Translator path="components.organisms.chat.dropScreen.dropYourFilesHere" />
</Typography>
</Stack>
Expand Down
1 change: 1 addition & 0 deletions libs/react-client/src/useChatData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IToken {
id: number | string;
token: string;
isSequence: boolean;
isInput: boolean;
}

const useChatData = () => {
Expand Down
19 changes: 14 additions & 5 deletions libs/react-client/src/useChatSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,20 @@ const useChatSession = () => {
setMessages((oldMessages) => addMessage(oldMessages, message));
});

socket.on('stream_token', ({ id, token, isSequence }: IToken) => {
setMessages((oldMessages) =>
updateMessageContentById(oldMessages, id, token, isSequence)
);
});
socket.on(
'stream_token',
({ id, token, isSequence, isInput }: IToken) => {
setMessages((oldMessages) =>
updateMessageContentById(
oldMessages,
id,
token,
isSequence,
isInput
)
);
}
);

socket.on('ask', ({ msg, spec }, callback) => {
setAskUser({ spec, callback });
Expand Down
15 changes: 12 additions & 3 deletions libs/react-client/src/utils/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,10 @@ const updateMessageContentById = (
messages: IStep[],
messageId: number | string,
updatedContent: string,
isSequence: boolean
isSequence: boolean,
isInput: boolean
): IStep[] => {
const nextMessages = [...messages];

for (let index = 0; index < nextMessages.length; index++) {
const msg = nextMessages[index];

Expand All @@ -221,6 +221,14 @@ const updateMessageContentById = (
} else {
msg.content += updatedContent;
}
} else if (isInput) {
if ('input' in msg && msg.input !== undefined) {
if (isSequence) {
msg.input = updatedContent;
} else {
msg.input += updatedContent;
}
}
} else {
if ('output' in msg && msg.output !== undefined) {
if (isSequence) {
Expand All @@ -237,7 +245,8 @@ const updateMessageContentById = (
msg.steps,
messageId,
updatedContent,
isSequence
isSequence,
isInput
);
nextMessages[index] = { ...msg };
}
Expand Down
Loading