АЛЕРТ! Братишки из Langchain в новой версии фреймворка чутка изменили api класса BaseMessage и еще кое-че по мелочи, поэтому теперь: 1) В узле summarizeConversation для удаления сообщений надо проверить, имеют ли они id, (согласно обновленному api, поле id не только опционально, но даже если и присутствует, то может иметь тип undefined"), и тут можно просто сделать фильтрацию массива messages по критерию наличия полноценного id: const deleteMessages = messages .filter(m => m.id !== undefined) .slice(0, -1) .map(m => new RemoveMessage({ id: m.id as string })); 2) Лучше обойтись без кастомной функции isAiMessageWithToolCalls и вместо нее использовать готовый чекер isAIMessage от разрабов, а проверку на наличие НЕПУСТОГО поля tool_calls запихнуть в отдельную функцию hasToolCalls. Обновленный код в развилке shouldContinue будет: import { isAIMessage } from "@langchain/core/messages" const hasToolCalls = (message: BaseMessage): boolean => { return 'tool_calls' in message && Array.isArray(message.tool_calls) && message.tool_calls.length > 0; } const shouldContinue = (state: IState): 'summarize_conversation' | ("tools" | 'crypto_news_node')[] | typeof END => { const messages = state.messages const lastMessage = messages[messages.length - 1] const isAIMessageWithToolCalls = isAIMessage(lastMessage) && hasToolCalls(lastMessage) if (messages.length > 4 && !isAIMessageWithToolCalls) { return 'summarize_conversation' } if (isAIMessageWithToolCalls) { const { tool_calls } = lastMessage const toolCallResult = tool_calls!.map((tc) => { if (tc.name === 'web_search_crypto') { return 'crypto_news_node' } else { return 'tools' } }) return toolCallResult } return END } Обратите внимание, что здесь используется оператор non-null assertion (!) в "const toolCallResult = tool_calls!.map..." чтобы Typescript знал, что tool_calls существует, и не будет undefined, после того как прошло условие, проверяющее его на существование.
Не совсем. Хотя Solana показывает рост в числе новых разработчиков и занимает лидирующие позиции по использованию децентрализованных бирж (DEX), в последнее время наблюдается смещение потока средств обратно в Bitcoin и Ethereum. В начале декабря, Bitcoin и Ethereum продемонстрировали более быструю динамику роста по сравнению с Solana. В сочетании с тем, что Solana показала отрицательные изменения в цене за последние 7 и 30 дней, можно заключить, что в данный момент Solana не превосходит Bitcoin и Ethereum по показателям роста.
АЛЕРТ!
Братишки из Langchain в новой версии фреймворка чутка изменили api класса BaseMessage и еще кое-че по мелочи, поэтому теперь:
1) В узле summarizeConversation для удаления сообщений надо проверить, имеют ли они id, (согласно обновленному api, поле id не только опционально, но даже если и присутствует, то может иметь тип undefined"), и тут можно просто сделать фильтрацию массива messages по критерию наличия полноценного id:
const deleteMessages = messages
.filter(m => m.id !== undefined)
.slice(0, -1)
.map(m => new RemoveMessage({ id: m.id as string }));
2) Лучше обойтись без кастомной функции isAiMessageWithToolCalls и вместо нее использовать готовый чекер isAIMessage от разрабов, а проверку на наличие НЕПУСТОГО поля tool_calls запихнуть в отдельную функцию hasToolCalls. Обновленный код в развилке shouldContinue будет:
import { isAIMessage } from "@langchain/core/messages"
const hasToolCalls = (message: BaseMessage): boolean => {
return 'tool_calls' in message &&
Array.isArray(message.tool_calls) &&
message.tool_calls.length > 0;
}
const shouldContinue = (state: IState):
'summarize_conversation' | ("tools" | 'crypto_news_node')[] | typeof END => {
const messages = state.messages
const lastMessage = messages[messages.length - 1]
const isAIMessageWithToolCalls = isAIMessage(lastMessage) && hasToolCalls(lastMessage)
if (messages.length > 4 && !isAIMessageWithToolCalls) {
return 'summarize_conversation'
}
if (isAIMessageWithToolCalls) {
const { tool_calls } = lastMessage
const toolCallResult = tool_calls!.map((tc) => {
if (tc.name === 'web_search_crypto') {
return 'crypto_news_node'
} else {
return 'tools'
}
})
return toolCallResult
}
return END
}
Обратите внимание, что здесь используется оператор non-null assertion (!) в "const toolCallResult = tool_calls!.map..." чтобы Typescript знал, что tool_calls существует, и не будет undefined, после того как прошло условие, проверяющее его на существование.
3) В узле cryptoNewsNode по аналогии с функцией shouldContinue надо поменять условие для запуска подграфа, добавить оператор "!" и также проверить, существует ли webSearchTool (плюс явно указать тип string для его поля id):
const cryptoNewsNode = async (state: IState): Promise => {
const { messages } = state
const userMessages = messages.filter(m => m.getType() === 'human') as HumanMessage[]
const lastUserQuery = userMessages[userMessages.length - 1].content as string
const lastMessage = messages[messages.length - 1]
if (isAIMessage(lastMessage) && hasToolCalls(lastMessage)) {
const webSearchTool = lastMessage.tool_calls!.find((tc) => tc.name === 'web_search_crypto')
if (!webSearchTool) {
throw new Error('ToolCall not found')
}
const { queries, token } = webSearchTool.args as IWebSearchToolArgs
const { aiResponseMessage }: ICryptoNewsGraphState = await cryptoNewsGraph.invoke({
initialQuery: lastUserQuery,
toolCallArgs: {
queries,
token
}
})
return {
messages: [
new ToolMessage({
id: uuidv4(),
content: `News retrieved. Queries used: ${queries.join(', ')}`,
tool_call_id: webSearchTool.id as string
}),
aiResponseMessage
]
}
} else {
throw new Error('Exprected AIMessage')
}
}
4) В узле summarizeTokenNews новостного подграфа тоже нужно убедиться, что token существует, добавив такую проверку перед вызовом инструмента cryptoTool:
if (!token) {
throw new Error('Token is undefined');
}
Естественно, в некст ролике всё исправлю.
Ура, наконец-то вторая часть про ИИ-агенты! Эдвард Билл лучший программист💪
Ну и как там в Египте?
0:46 брат, это было мощно
ахах да дальше тоже грязь есть
@@napasnation19 я всё посмотрел, очень хорошо было
Я правильно понял, что Solana демонстрирует устойчивый рост, превосходя Etherium и Bitcoin?
Не совсем. Хотя Solana показывает рост в числе новых разработчиков и занимает лидирующие позиции по использованию децентрализованных бирж (DEX), в последнее время наблюдается смещение потока средств обратно в Bitcoin и Ethereum. В начале декабря, Bitcoin и Ethereum продемонстрировали более быструю динамику роста по сравнению с Solana. В сочетании с тем, что Solana показала отрицательные изменения в цене за последние 7 и 30 дней, можно заключить, что в данный момент Solana не превосходит Bitcoin и Ethereum по показателям роста.
@@napasnation19 понял, спасибо👍