Skip to content
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
19 changes: 18 additions & 1 deletion bot/engine/src/main/kotlin/engine/config/RAGAnswerHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import ai.tock.genai.orchestratorclient.responses.TextWithFootnotes
import ai.tock.genai.orchestratorclient.retrofit.GenAIOrchestratorBusinessError
import ai.tock.genai.orchestratorclient.retrofit.GenAIOrchestratorValidationError
import ai.tock.genai.orchestratorclient.services.RAGService
import ai.tock.genai.orchestratorcore.models.observability.LangfuseObservabilitySetting
import ai.tock.genai.orchestratorcore.utils.VectorStoreUtils
import ai.tock.shared.*
import engine.config.AbstractProactiveAnswerHandler
Expand Down Expand Up @@ -70,6 +71,9 @@ object RAGAnswerHandler : AbstractProactiveAnswerHandler {
// Handle the RAG answer
if (noAnswerStory == null && answer != null) {
logger.info { "Send RAG answer." }

val modifiedObservabilityInfo = observabilityInfo?.let { updateObservabilityInfo(this, it) }

send(
SendSentenceWithFootnotes(
botId, connectorId, userId, text = answer.text, footnotes = answer.footnotes.map {
Expand All @@ -79,7 +83,8 @@ object RAGAnswerHandler : AbstractProactiveAnswerHandler {
it.score
)
}.toMutableList(),
metadata = ActionMetadata(isGenAiRagAnswer = true, observabilityInfo = observabilityInfo)
// modifiedObservabilityInfo includes the public langfuse URL if filled.
metadata = ActionMetadata(isGenAiRagAnswer = true, observabilityInfo = modifiedObservabilityInfo)
)
)
} else {
Expand All @@ -90,6 +95,18 @@ object RAGAnswerHandler : AbstractProactiveAnswerHandler {
}
}

private fun updateObservabilityInfo(botBus: BotBus, info: ObservabilityInfo): ObservabilityInfo {
val config = botBus.botDefinition.observabilityConfiguration
if (config?.enabled == true && config.setting is LangfuseObservabilitySetting<*>) {
val setting = config.setting as LangfuseObservabilitySetting<*>
val publicUrl = setting.publicUrl
if (!publicUrl.isNullOrBlank()) {
return info.copy(traceUrl = info.traceUrl.replace(setting.url, publicUrl))
}
}
return info
}

/**
* Manage story redirection when no answer redirection is filled
* Use the handler of the configured story otherwise launch default unknown story
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@
title: Gen AI - Observability Settings
---

# Le menu *Gen AI - Observability Settings*
# The _Gen AI - Observability Settings_ Menu

- L'observabilité des modèles de langage (LLM Observability) aide à surveiller, d'analyser et de comprendre le comportement des modèles de langage à grande échelle.
- Cela inclut la collecte de données sur leurs performances, la détection d'anomalies et la compréhension des erreurs qu'ils peuvent produire.
- L'objectif est de garantir que ces modèles fonctionnent de manière fiable, transparente, en fournissant des informations qui permettent d'améliorer leur performance et de corriger les problèmes potentiels.
- Plus précisément, nous pourrons :
- Voir les différents enchainements d'appels de LLM avec le prompt d'entrée et de sortie
- Analyser les portions de documents contextuels utilisés
- Suivre les informations et les métriques sur les coûts, le nombre de jetons consommés, la latence, etc.
- **LLM Observability** helps monitor, analyze, and understand the behavior of large-scale language models.
- This includes collecting data on their performance, detecting anomalies, and understanding the errors they may produce.
- The goal is to ensure that these models operate reliably and transparently, providing insights that help improve their performance and address potential issues.
- Specifically, we can:
- View different sequences of LLM calls, including input and output prompts.
- Analyze contextual document sections used.
- Track information and metrics such as costs, token consumption, latency, etc.


> Pour accéder à cette page il faut bénéficier du rôle **_botUser_**.
> <br />( plus de détails sur les rôles dans [securité]() ).
> To access this page, you must have the **_botUser_** role.
> <br />(More details on roles can be found in [security](../../../../../admin/securite#rôles)).

## Configuration
Pour permettre à Tock de se connecter à un outil d'observabilité, un écran de configuration a été mis en place :
To enable Tock to connect to an observability tool, a configuration screen has been set up:

![LLM Observability](../../../../../img/gen-ai/gen-ai-feature-observability.png "Configuration screen for the AI observability tool")

## Public URL Configuration

![LLM Observability](../../../../img/gen-ai/gen-ai-feature-observability.png "Ecran de configuration de l'outil d'observation de l'IA")
- The **Public URL** field allows specifying an externally accessible URL for observability tools such as Langfuse.
- This URL will be used in the frontend interface to redirect users to observability traces, replacing the internal URL, which may not be publicly accessible.

## Utilisation
## Usage

- Voici la [liste des fournisseurs d'observabilité des LLM](../../../../user/studio/gen-ai/providers/gen-ai-provider-observability.md) qui sont pris en compte par Tock.
- Veuillez vous référer à la documentation de chaque outil pour comprendre comment l'utiliser.
- Here is the [list of LLM observability providers](../../providers/gen-ai-provider-observability) supported by Tock.
- Please refer to each tool's documentation to understand how to use it.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ Pour permettre à Tock de se connecter à un outil d'observabilité, un écran d

![LLM Observability](../../../../img/gen-ai/gen-ai-feature-observability.png "Ecran de configuration de l'outil d'observation de l'IA")

## Configuration d'URL Publique

- Le champ **Public URL** permet de spécifier une URL accessible depuis l'extérieur pour les outils d'observabilité comme Langfuse.
- Cette URL sera utilisée dans l'interface frontend pour rediriger les utilisateurs vers les traces d'observabilité, remplaçant l'URL interne qui pourrait ne pas être accessible publiquement.

## Utilisation

- Voici la [liste des fournisseurs d'observabilité des LLM](../../../../user/studio/gen-ai/providers/gen-ai-provider-observability.md) qui sont pris en compte par Tock.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object ObservabilitySettingMapper {
when (this) {
is LangfuseObservabilitySetting -> {
val secretKey = SecurityUtils.fetchSecretKeyValue(secretKey)
return LangfuseObservabilitySetting(secretKey, publicKey, url)
return LangfuseObservabilitySetting(secretKey, publicKey, url, publicUrl)
}

else ->
Expand Down Expand Up @@ -64,9 +64,8 @@ object ObservabilitySettingMapper {
when (this) {
is LangfuseObservabilitySetting -> {
val secretKey = SecurityUtils.createSecretKey(namespace, botId, feature, secretKey, rawByForce)
return LangfuseObservabilitySetting(secretKey, publicKey, url)
return LangfuseObservabilitySetting(secretKey, publicKey, url, publicUrl.takeIf {!it.isNullOrBlank()})
}

else ->
throw IllegalArgumentException("Unsupported Observability Setting")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ import ai.tock.shared.security.key.HasSecretKey
data class LangfuseObservabilitySetting<T>(
override val secretKey: T,
val publicKey: String,
val url: String
val url: String,
val publicUrl : String? = null,
) : ObservabilitySettingBase<T>(ObservabilityProvider.Langfuse), HasSecretKey<T>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#
"""Model for creating LangfuseObservabilitySetting."""

from typing import Literal
from typing import Literal, Optional

from pydantic import AnyUrl, Field

Expand Down Expand Up @@ -42,6 +42,11 @@ class LangfuseObservabilitySetting(BaseObservabilitySetting):
url: AnyUrl = Field(
description='The Langfuse server url', examples=['https://cloud.langfuse.com'], default='http://localhost:3000'
)
public_url: Optional[AnyUrl] = Field(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have a public URL here as it's not used in the orchestrator.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we share the same data model between the orchestrator and the bot admin BotObservabilityConfigurationDTO.setting is LangfuseObservabilitySetting which came from the Orchestrator API contract we should have a BotAdmin API contract decorrelated from the ochestrator contract to avoid this.

default=None,
description="Optional public URL for Langfuse server",
examples=["https://public.langfuse.com"]
)
secret_key: SecretKey = Field(
description='Stores the secret key used to authenticate requests to the Observability Provider API.',
examples=[RawSecretKey(secret='sk-********************be8f')],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async def get_observability_provider_setting_by_id(
provider=ObservabilityProvider.LANGFUSE,
secret_key=RawSecretKey(secret='sk-********************be8f'),
public_key='pk-lf-5e374dc6-e194-4b37-9c07-b77e68ef7d2c',
url='https://cloud.langfuse.com'
url='https://cloud.langfuse.com',
)


Expand Down