Skip to content

Commit acfc4ec

Browse files
committed
fix not display
1 parent 90a55f3 commit acfc4ec

File tree

4 files changed

+71
-69
lines changed

4 files changed

+71
-69
lines changed

templates/components/agents/python/blog/app/workflows/models.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from typing import Any, Dict, List, Literal
22

3-
from app.api.routers.models import SourceNodes
4-
from llama_index.core.schema import Node, NodeWithScore
3+
from llama_index.core.schema import NodeWithScore
54
from llama_index.core.workflow import Event
65

6+
from app.api.routers.models import SourceNodes
7+
78

89
# Workflow events
910
class PlanResearchEvent(Event):
@@ -13,7 +14,7 @@ class PlanResearchEvent(Event):
1314
class ResearchEvent(Event):
1415
question_id: str
1516
question: str
16-
context_nodes: List[NodeWithScore | Node]
17+
context_nodes: List[NodeWithScore]
1718

1819

1920
class CollectAnswersEvent(Event):

templates/components/agents/python/blog/app/workflows/writer.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,6 @@
33
import uuid
44
from typing import Any, Dict, List, Optional
55

6-
from app.engine.index import IndexConfig, get_index
7-
from app.workflows.agents import plan_research, research, write_report
8-
from app.workflows.models import (
9-
CollectAnswersEvent,
10-
DataEvent,
11-
PlanResearchEvent,
12-
ResearchEvent,
13-
SourceNodesEvent,
14-
WriteReportEvent,
15-
)
166
from llama_index.core.indices.base import BaseIndex
177
from llama_index.core.memory import ChatMemoryBuffer
188
from llama_index.core.memory.simple_composable_memory import SimpleComposableMemory
@@ -26,7 +16,18 @@
2616
step,
2717
)
2818

29-
logger = logging.getLogger(__name__)
19+
from app.engine.index import IndexConfig, get_index
20+
from app.workflows.agents import plan_research, research, write_report
21+
from app.workflows.models import (
22+
CollectAnswersEvent,
23+
DataEvent,
24+
PlanResearchEvent,
25+
ResearchEvent,
26+
SourceNodesEvent,
27+
WriteReportEvent,
28+
)
29+
30+
logger = logging.getLogger("uvicorn")
3031
logger.setLevel(logging.INFO)
3132

3233

@@ -45,7 +46,7 @@ def create_workflow(
4546
return WriterWorkflow(
4647
index=index,
4748
chat_history=chat_history,
48-
**kwargs,
49+
timeout=120.0,
4950
)
5051

5152

@@ -67,22 +68,20 @@ class WriterWorkflow(Workflow):
6768
context_nodes: List[Node]
6869
index: BaseIndex
6970
user_request: str
70-
stream: bool = False
71+
stream: bool = True
7172

7273
def __init__(
7374
self,
7475
index: BaseIndex,
7576
chat_history: Optional[List[ChatMessage]] = None,
76-
stream: bool = False,
77-
timeout: Optional[float] = 120.0,
77+
stream: bool = True,
7878
**kwargs,
7979
):
8080
super().__init__(**kwargs)
8181
self.index = index
8282
self.context_nodes = []
8383
self.stream = stream
8484
self.chat_history = chat_history
85-
self.timeout = timeout
8685
self.memory = SimpleComposableMemory.from_defaults(
8786
primary_memory=ChatMemoryBuffer.from_defaults(
8887
chat_history=chat_history,
@@ -142,7 +141,7 @@ async def analyze(
142141
"""
143142
Analyze the retrieved information
144143
"""
145-
print("Analyzing the retrieved information")
144+
logger.info("Analyzing the retrieved information")
146145
ctx.write_event_to_stream(
147146
DataEvent(
148147
type="analyze",
@@ -262,7 +261,7 @@ async def collect_answers(
262261
content=f"<Question>{result.question}</Question>\n<Answer>{result.answer}</Answer>",
263262
)
264263
)
265-
ctx.set("n_questions", 0)
264+
await ctx.set("n_questions", 0)
266265
self.memory.put(
267266
message=ChatMessage(
268267
role=MessageRole.ASSISTANT,
@@ -276,6 +275,7 @@ async def report(self, ctx: Context, ev: WriteReportEvent) -> StopEvent:
276275
"""
277276
Report the answers
278277
"""
278+
logger.info("Writing the report")
279279
res = await write_report(
280280
memory=self.memory,
281281
user_request=self.user_request,

templates/types/streaming/nextjs/app/components/ui/chat/chat-message-content.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function ChatMessageContent() {
2525
},
2626
// add the writer card
2727
{
28-
position: ContentPosition.AFTER_EVENTS,
28+
position: ContentPosition.CHAT_EVENTS,
2929
component: <WriterCard message={message} />,
3030
},
3131
{

templates/types/streaming/nextjs/app/components/ui/chat/custom/writer-card.tsx

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
NotebookPen,
99
Search,
1010
} from "lucide-react";
11-
import { useEffect, useState } from "react";
11+
import { useMemo } from "react";
1212
import {
1313
Collapsible,
1414
CollapsibleContent,
@@ -45,42 +45,49 @@ type WriterState = {
4545
};
4646
};
4747

48-
// Update the state based on the event
49-
const updateState = (state: WriterState, event: WriterEvent): WriterState => {
48+
const stateIcon: Record<EventState, React.ReactNode> = {
49+
pending: <Clock className="w-4 h-4 text-yellow-500" />,
50+
inprogress: <CircleDashed className="w-4 h-4 text-blue-500 animate-spin" />,
51+
done: <CheckCircle2 className="w-4 h-4 text-green-500" />,
52+
error: <AlertCircle className="w-4 h-4 text-red-500" />,
53+
};
54+
55+
// Transform the state based on the event without mutations
56+
const transformState = (
57+
state: WriterState,
58+
event: WriterEvent,
59+
): WriterState => {
5060
switch (event.type) {
5161
case "answer": {
5262
const { id, question, answer } = event.data;
5363
if (!id || !question) return state;
5464

55-
const questions = state.analyze.questions;
56-
const existingQuestion = questions.find((q) => q.id === id);
57-
58-
const updatedQuestions = existingQuestion
59-
? questions.map((q) =>
60-
q.id === id
61-
? {
62-
...existingQuestion,
63-
state: event.state,
64-
answer: answer || existingQuestion.answer,
65-
}
66-
: q,
67-
)
68-
: [
69-
...questions,
65+
const updatedQuestions = state.analyze.questions.map((q) => {
66+
if (q.id !== id) return q;
67+
return {
68+
...q,
69+
state: event.state,
70+
answer: answer ?? q.answer,
71+
};
72+
});
73+
74+
const newQuestion = !state.analyze.questions.some((q) => q.id === id)
75+
? [
7076
{
7177
id,
7278
question,
73-
answer: answer || null,
79+
answer: answer ?? null,
7480
state: event.state,
7581
isOpen: false,
7682
},
77-
];
83+
]
84+
: [];
7885

7986
return {
8087
...state,
8188
analyze: {
8289
...state.analyze,
83-
questions: updatedQuestions,
90+
questions: [...updatedQuestions, ...newQuestion],
8491
},
8592
};
8693
}
@@ -100,36 +107,30 @@ const updateState = (state: WriterState, event: WriterEvent): WriterState => {
100107
}
101108
};
102109

103-
export function WriterCard({ message }: { message: Message }) {
104-
const [state, setState] = useState<WriterState>({
110+
// Convert writer events to state
111+
const writeEventsToState = (events: WriterEvent[] | undefined): WriterState => {
112+
if (!events?.length) {
113+
return {
114+
retrieve: { state: null },
115+
analyze: { state: null, questions: [] },
116+
};
117+
}
118+
119+
const initialState: WriterState = {
105120
retrieve: { state: null },
106121
analyze: { state: null, questions: [] },
107-
});
122+
};
108123

124+
return events.reduce(
125+
(acc: WriterState, event: WriterEvent) => transformState(acc, event),
126+
initialState,
127+
);
128+
};
129+
130+
export function WriterCard({ message }: { message: Message }) {
109131
const writerEvents = message.annotations as WriterEvent[] | undefined;
110132

111-
useEffect(() => {
112-
if (writerEvents?.length) {
113-
writerEvents.forEach((event) => {
114-
setState((currentState) => updateState(currentState, event));
115-
});
116-
}
117-
}, [writerEvents]);
118-
119-
const getStateIcon = (state: EventState | null) => {
120-
switch (state) {
121-
case "pending":
122-
return <Clock className="w-4 h-4 text-yellow-500" />;
123-
case "inprogress":
124-
return <CircleDashed className="w-4 h-4 text-blue-500 animate-spin" />;
125-
case "done":
126-
return <CheckCircle2 className="w-4 h-4 text-green-500" />;
127-
case "error":
128-
return <AlertCircle className="w-4 h-4 text-red-500" />;
129-
default:
130-
return null;
131-
}
132-
};
133+
const state = useMemo(() => writeEventsToState(writerEvents), [writerEvents]);
133134

134135
if (!writerEvents?.length) {
135136
return null;
@@ -167,7 +168,7 @@ export function WriterCard({ message }: { message: Message }) {
167168
<CollapsibleTrigger className="w-full">
168169
<div className="flex items-center gap-2 p-3 hover:bg-gray-50 transition-colors rounded-lg border border-gray-200">
169170
<div className="flex-shrink-0">
170-
{getStateIcon(question.state)}
171+
{stateIcon[question.state]}
171172
</div>
172173
<span className="font-medium text-left flex-1">
173174
{question.question}

0 commit comments

Comments
 (0)