LunaryAI automatic Thread and User tracking (#3233)

* Lunary Thread/User tracking

* Clean console logs

* Clean

* Remove commented lines

* Remove commented line
This commit is contained in:
Vincelwt 2024-09-26 12:01:33 +01:00 committed by GitHub
parent 8690c43ef5
commit 18f916a7e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 32683 additions and 32568 deletions

View File

@ -8,22 +8,23 @@ class LunaryApi implements INodeCredential {
inputs: INodeParams[]
constructor() {
this.label = 'Lunary API'
this.label = 'Lunary AI'
this.name = 'lunaryApi'
this.version = 1.0
this.description = 'Refer to <a target="_blank" href="https://lunary.ai/docs">official guide</a> to get APP ID'
this.description =
'Refer to the <a target="_blank" href="https://lunary.ai/docs?utm_source=flowise">official guide</a> to get a public key.'
this.inputs = [
{
label: 'APP ID',
label: 'Public Key / Project ID',
name: 'lunaryAppId',
type: 'password',
placeholder: '<Lunary_APP_ID>'
type: 'string',
placeholder: '<Lunary_PROJECT_ID>'
},
{
label: 'Endpoint',
name: 'lunaryEndpoint',
type: 'string',
default: 'https://app.lunary.ai'
default: 'https://api.lunary.ai'
}
]
}

View File

@ -1,7 +1,26 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="15.9562" cy="16.0002" rx="4.3478" ry="4.34782" stroke="black" stroke-width="2"/>
<path d="M23.5651 23.6086C21.603 25.621 18.8688 26.8695 15.8445 26.8695C10.2386 26.8695 5.62933 22.5797 5.08691 17.0869" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M8.34766 8.23751C10.314 6.3155 13.0074 5.13037 15.9785 5.13037C21.6311 5.13037 26.2789 9.42024 26.8258 14.913" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M9.5217 9.47815C9.5217 10.7268 8.50948 11.739 7.26085 11.739C6.01222 11.739 5 10.7268 5 9.47815C5 8.22951 6.01222 7.21729 7.26085 7.21729C8.50948 7.21729 9.5217 8.22951 9.5217 9.47815Z" fill="black" stroke="black" stroke-width="2"/>
<path d="M28.0002 21.4347C28.0002 22.6833 26.988 23.6956 25.7394 23.6956C24.4907 23.6956 23.4785 22.6833 23.4785 21.4347C23.4785 20.186 24.4907 19.1738 25.7394 19.1738C26.988 19.1738 28.0002 20.186 28.0002 21.4347Z" fill="black" stroke="black" stroke-width="2"/>
</svg>
<svg height="216" viewBox="0 0 216 216" width="216" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="blue-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#006dcc;stop-opacity:1" />
<stop offset="100%" style="stop-color:#3aa4ff;stop-opacity:1" />
</linearGradient>
<filter id="shadow" x="-2%" y="-2%" width="110%" height="110%" filterUnits="objectBoundingBox" >
<feOffset result="offOut" in="SourceAlpha" dx="2" dy="3" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="4" />
<feComponentTransfer>
<feFuncA type="linear" slope="0.1" />
</feComponentTransfer>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<g fill="none" fill-rule="evenodd">
<rect x="8" y="8" width="200" height="200" rx="45" ry="45" fill="url(#blue-gradient)" fill-rule="nonzero" filter="url(#shadow)" style="filter: drop-shadow(2px 3px 4px rgba(128, 128, 128, 0.8));" />
<g stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="15" transform="translate(42 42)">
<path d="m132 58c-.991994-7.1686791-3.094482-13.9665431-6.127891-20.2149374-9.6743-19.9276923-28.8172875-34.26655561-51.6037985-37.22124123-26.5813666-3.47510895-52.6608614 9.32644484-66.2683105 32.52890253"/>
<path d="m0 74c3.9198666 28.335939 25.2597454 51.079666 53.1909971 56.69018 27.9312514 5.610514 56.3393579-7.140402 70.8090029-31.782463"/>
<path d="m123.5 108c4.69442 0 8.5-3.80558 8.5-8.5 0-4.6944203-3.80558-8.5-8.5-8.5s-8.5 3.8055797-8.5 8.5c0 4.69442 3.80558 8.5 8.5 8.5z"/>
<path d="m8.5 42c4.6944204 0 8.5-3.8055796 8.5-8.5s-3.8055796-8.5-8.5-8.5c-4.69442035 0-8.5 3.8055796-8.5 8.5s3.80557965 8.5 8.5 8.5z"/>
<path d="m66 91c13.8071191 0 25-11.1928809 25-25 0-13.8071187-11.1928809-25-25-25-13.8071187 0-25 11.1928813-25 25 0 13.8071191 11.1928813 25 25 25z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -93,7 +93,7 @@
"linkifyjs": "^4.1.1",
"llamaindex": "^0.3.13",
"lodash": "^4.17.21",
"lunary": "^0.7.10",
"lunary": "^0.7.12",
"mammoth": "^1.5.1",
"meilisearch": "^0.41.0",
"moment": "^2.29.3",

View File

@ -14,8 +14,9 @@ import { AgentAction } from '@langchain/core/agents'
import { LunaryHandler } from '@langchain/community/callbacks/handlers/lunary'
import { getCredentialData, getCredentialParam, getEnvironmentVariable } from './utils'
import { ICommonObject, INodeData, IServerSideEventStreamer } from './Interface'
import { ICommonObject, IDatabaseEntity, INodeData, IServerSideEventStreamer } from './Interface'
import { LangWatch, LangWatchSpan, LangWatchTrace, autoconvertTypedValues } from 'langwatch'
import { DataSource } from 'typeorm'
interface AgentRun extends Run {
actions: AgentAction[]
@ -90,6 +91,7 @@ export class ConsoleCallbackHandler extends BaseTracer {
onChainStart(run: Run) {
const crumbs = this.getBreadcrumbs(run)
this.logger.verbose(`[chain/start] [${crumbs}] Entering Chain run with input: ${tryJsonStringify(run.inputs, '[inputs]')}`)
}
@ -235,6 +237,78 @@ export class CustomChainHandler extends BaseCallbackHandler {
}
}
class ExtendedLunaryHandler extends LunaryHandler {
chatId: string
appDataSource: DataSource
databaseEntities: IDatabaseEntity
currentRunId: string | null
thread: any
constructor({ flowiseOptions, ...options }: any) {
super(options)
this.appDataSource = flowiseOptions.appDataSource
this.databaseEntities = flowiseOptions.databaseEntities
this.chatId = flowiseOptions.chatId
}
async initThread() {
const entity = await this.appDataSource.getRepository(this.databaseEntities['Lead']).findOne({
where: {
chatId: this.chatId
}
})
this.thread = lunary.openThread({
id: this.chatId,
userId: entity?.email ?? entity?.id,
userProps: {
name: entity?.name ?? undefined,
email: entity?.email ?? undefined,
phone: entity?.phone ?? undefined
}
})
}
async handleChainStart(chain: any, inputs: any, runId: string, parentRunId?: string, tags?: string[], metadata?: any): Promise<void> {
// First chain (no parent run id) is the user message
if (this.chatId && !parentRunId) {
if (!this.thread) {
await this.initThread()
}
const messageText = inputs.input
const messageId = this.thread.trackMessage({
content: messageText,
role: 'user'
})
// Track top level chain id for knowing when we got the final reply
this.currentRunId = runId
// Use the messageId as the parent of the chain for reconciliation
super.handleChainStart(chain, inputs, runId, messageId, tags, metadata)
} else {
super.handleChainStart(chain, inputs, runId, parentRunId, tags, metadata)
}
}
async handleChainEnd(outputs: ChainValues, runId: string): Promise<void> {
if (this.chatId && runId === this.currentRunId) {
const answer = outputs.output
this.thread.trackMessage({
content: answer,
role: 'assistant'
})
this.currentRunId = null
}
super.handleChainEnd(outputs, runId)
}
}
export const additionalCallbacks = async (nodeData: INodeData, options: ICommonObject) => {
try {
if (!options.analytic) return []
@ -293,19 +367,22 @@ export const additionalCallbacks = async (nodeData: INodeData, options: ICommonO
const handler = new CallbackHandler(langFuseOptions)
callbacks.push(handler)
} else if (provider === 'lunary') {
const lunaryAppId = getCredentialParam('lunaryAppId', credentialData, nodeData)
const lunaryPublicKey = getCredentialParam('lunaryAppId', credentialData, nodeData)
const lunaryEndpoint = getCredentialParam('lunaryEndpoint', credentialData, nodeData)
let lunaryFields = {
appId: lunaryAppId,
apiUrl: lunaryEndpoint ?? 'https://app.lunary.ai'
publicKey: lunaryPublicKey,
apiUrl: lunaryEndpoint ?? 'https://api.lunary.ai',
runtime: 'flowise',
flowiseOptions: options
}
if (nodeData?.inputs?.analytics?.lunary) {
lunaryFields = { ...lunaryFields, ...nodeData?.inputs?.analytics?.lunary }
}
const handler = new LunaryHandler(lunaryFields)
const handler = new ExtendedLunaryHandler(lunaryFields)
callbacks.push(handler)
} else if (provider === 'langWatch') {
const langWatchApiKey = getCredentialParam('langWatchApiKey', credentialData, nodeData)
@ -376,12 +453,13 @@ export class AnalyticHandler {
})
this.handlers['langFuse'] = { client: langfuse }
} else if (provider === 'lunary') {
const lunaryAppId = getCredentialParam('lunaryAppId', credentialData, this.nodeData)
const lunaryPublicKey = getCredentialParam('lunaryAppId', credentialData, this.nodeData)
const lunaryEndpoint = getCredentialParam('lunaryEndpoint', credentialData, this.nodeData)
lunary.init({
appId: lunaryAppId,
apiUrl: lunaryEndpoint
publicKey: lunaryPublicKey,
apiUrl: lunaryEndpoint,
runtime: 'flowise'
})
this.handlers['lunary'] = { client: lunary }
@ -487,7 +565,6 @@ export class AnalyticHandler {
await monitor.trackEvent('chain', 'start', {
runId,
name,
userId: this.options.chatId,
input,
...this.nodeData?.inputs?.analytics?.lunary
})
@ -686,7 +763,6 @@ export class AnalyticHandler {
runId,
parentRunId: chainEventId,
name,
userId: this.options.chatId,
input
})
this.handlers['lunary'].llmEvent = { [runId]: runId }
@ -843,7 +919,6 @@ export class AnalyticHandler {
runId,
parentRunId: chainEventId,
name,
userId: this.options.chatId,
input
})
this.handlers['lunary'].toolEvent = { [runId]: runId }

View File

@ -38,6 +38,7 @@ import { ChatMessage } from '../database/entities/ChatMessage'
import { Credential } from '../database/entities/Credential'
import { Tool } from '../database/entities/Tool'
import { Assistant } from '../database/entities/Assistant'
import { Lead } from '../database/entities/Lead'
import { DataSource } from 'typeorm'
import { CachePool } from '../CachePool'
import { Variable } from '../database/entities/Variable'
@ -55,6 +56,7 @@ export const databaseEntities: IDatabaseEntity = {
ChatMessage: ChatMessage,
Tool: Tool,
Credential: Credential,
Lead: Lead,
Assistant: Assistant,
Variable: Variable,
DocumentStore: DocumentStore,

View File

@ -1,7 +1,26 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="15.9562" cy="16.0002" rx="4.3478" ry="4.34782" stroke="black" stroke-width="2"/>
<path d="M23.5651 23.6086C21.603 25.621 18.8688 26.8695 15.8445 26.8695C10.2386 26.8695 5.62933 22.5797 5.08691 17.0869" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M8.34766 8.23751C10.314 6.3155 13.0074 5.13037 15.9785 5.13037C21.6311 5.13037 26.2789 9.42024 26.8258 14.913" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M9.5217 9.47815C9.5217 10.7268 8.50948 11.739 7.26085 11.739C6.01222 11.739 5 10.7268 5 9.47815C5 8.22951 6.01222 7.21729 7.26085 7.21729C8.50948 7.21729 9.5217 8.22951 9.5217 9.47815Z" fill="black" stroke="black" stroke-width="2"/>
<path d="M28.0002 21.4347C28.0002 22.6833 26.988 23.6956 25.7394 23.6956C24.4907 23.6956 23.4785 22.6833 23.4785 21.4347C23.4785 20.186 24.4907 19.1738 25.7394 19.1738C26.988 19.1738 28.0002 20.186 28.0002 21.4347Z" fill="black" stroke="black" stroke-width="2"/>
</svg>
<svg height="216" viewBox="0 0 216 216" width="216" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="blue-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#006dcc;stop-opacity:1" />
<stop offset="100%" style="stop-color:#3aa4ff;stop-opacity:1" />
</linearGradient>
<filter id="shadow" x="-2%" y="-2%" width="110%" height="110%" filterUnits="objectBoundingBox" >
<feOffset result="offOut" in="SourceAlpha" dx="2" dy="3" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="4" />
<feComponentTransfer>
<feFuncA type="linear" slope="0.1" />
</feComponentTransfer>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<g fill="none" fill-rule="evenodd">
<rect x="8" y="8" width="200" height="200" rx="45" ry="45" fill="url(#blue-gradient)" fill-rule="nonzero" filter="url(#shadow)" style="filter: drop-shadow(2px 3px 4px rgba(128, 128, 128, 0.5));" />
<g stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="15" transform="translate(51 51) scale(0.89)">
<path d="m132 58c-.991994-7.1686791-3.094482-13.9665431-6.127891-20.2149374-9.6743-19.9276923-28.8172875-34.26655561-51.6037985-37.22124123-26.5813666-3.47510895-52.6608614 9.32644484-66.2683105 32.52890253"/>
<path d="m0 74c3.9198666 28.335939 25.2597454 51.079666 53.1909971 56.69018 27.9312514 5.610514 56.3393579-7.140402 70.8090029-31.782463"/>
<path d="m123.5 108c4.69442 0 8.5-3.80558 8.5-8.5 0-4.6944203-3.80558-8.5-8.5-8.5s-8.5 3.8055797-8.5 8.5c0 4.69442 3.80558 8.5 8.5 8.5z"/>
<path d="m8.5 42c4.6944204 0 8.5-3.8055796 8.5-8.5s-3.8055796-8.5-8.5-8.5c-4.69442035 0-8.5 3.8055796-8.5 8.5s3.80557965 8.5 8.5 8.5z"/>
<path d="m66 91c13.8071191 0 25-11.1928809 25-25 0-13.8071187-11.1928809-25-25-25-13.8071187 0-25 11.1928813-25 25 0 13.8071191 11.1928813 25 25 25z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

File diff suppressed because it is too large Load Diff