Adds documentation and fixes
This commit is contained in:
319
docs/langfuse-guide.md
Normal file
319
docs/langfuse-guide.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# Guia de Integracao Langfuse
|
||||
|
||||
Este guia explica como o Langfuse esta integrado ao assistente e como utilizar suas funcionalidades de scoring e observabilidade.
|
||||
|
||||
## Indice
|
||||
|
||||
- [O que e Langfuse](#o-que-e-langfuse)
|
||||
- [Configuracao Inicial](#configuracao-inicial)
|
||||
- [Sistema de Scores](#sistema-de-scores)
|
||||
- [Adicionando Novos Scores](#adicionando-novos-scores)
|
||||
- [Visualizando Metricas](#visualizando-metricas)
|
||||
- [Boas Praticas](#boas-praticas)
|
||||
|
||||
## O que e Langfuse
|
||||
|
||||
Langfuse e uma plataforma de observabilidade para aplicacoes LLM que permite:
|
||||
|
||||
- Rastrear todas as chamadas ao modelo
|
||||
- Adicionar scores e metricas customizadas
|
||||
- Analisar performance e custos
|
||||
- Debugar conversas problematicas
|
||||
|
||||
## Configuracao Inicial
|
||||
|
||||
### 1. Credenciais
|
||||
|
||||
As credenciais do Langfuse sao armazenadas no AWS Secrets Manager:
|
||||
|
||||
```python
|
||||
# Recuperando credenciais
|
||||
from tools import secrets
|
||||
import json
|
||||
|
||||
secrets_data = json.loads(secrets.get_secret())
|
||||
public_key = secrets_data['api-langfuse-public']
|
||||
secret_key = secrets_data['api-langfuse-secret']
|
||||
```
|
||||
|
||||
### 2. Inicializacao do Cliente
|
||||
|
||||
```python
|
||||
from langfuse import Langfuse
|
||||
from langfuse.langchain import CallbackHandler
|
||||
|
||||
# Cliente principal para spans e scores
|
||||
langfuse = Langfuse(
|
||||
public_key=public_key,
|
||||
secret_key=secret_key,
|
||||
host="http://SEU_HOST_LANGFUSE:3000"
|
||||
)
|
||||
|
||||
# Callback handler para integracao automatica com LangChain
|
||||
langfuse_handler = CallbackHandler()
|
||||
```
|
||||
|
||||
### 3. Integracao com LangGraph
|
||||
|
||||
```python
|
||||
# Adicionar o handler na configuracao do agente
|
||||
config = {
|
||||
"configurable": {"thread_id": "abc123"},
|
||||
"callbacks": [langfuse_handler]
|
||||
}
|
||||
|
||||
# Executar o agente
|
||||
for step in agent_executor.stream({"messages": input_message}, config, stream_mode="values"):
|
||||
# processamento...
|
||||
pass
|
||||
|
||||
# IMPORTANTE: Flush para garantir envio dos dados
|
||||
langfuse.flush()
|
||||
```
|
||||
|
||||
## Sistema de Scores
|
||||
|
||||
### Scores Atuais
|
||||
|
||||
O sistema atual utiliza os seguintes scores:
|
||||
|
||||
| Score | Tipo | Descricao |
|
||||
|-------|------|-----------|
|
||||
| `Miss` | CATEGORICAL | Indica quando o agente nao encontrou a resposta |
|
||||
| `Origem` | CATEGORICAL | Canal de origem da pergunta (web, app, etc.) |
|
||||
| `Email` | CATEGORICAL | Email do usuario para rastreabilidade |
|
||||
|
||||
### Como os Scores sao Registrados
|
||||
|
||||
```python
|
||||
# Score de "Miss" - quando nao encontra resposta
|
||||
@tool
|
||||
def out_of_scope_and_dont_know_answer():
|
||||
with langfuse.start_as_current_span(name="my-operation") as span:
|
||||
span.score_trace(
|
||||
name="Miss",
|
||||
value="True",
|
||||
data_type="CATEGORICAL"
|
||||
)
|
||||
return "Mensagem de resposta padrao..."
|
||||
|
||||
# Scores de metadados - origem e email
|
||||
with langfuse.start_as_current_span(name="my-operation") as span:
|
||||
span.score_trace(
|
||||
name="Origem",
|
||||
value=origem,
|
||||
data_type="CATEGORICAL"
|
||||
)
|
||||
span.score_trace(
|
||||
name="Email",
|
||||
value=email,
|
||||
data_type="CATEGORICAL"
|
||||
)
|
||||
```
|
||||
|
||||
## Adicionando Novos Scores
|
||||
|
||||
### Tipos de Score Disponiveis
|
||||
|
||||
1. **CATEGORICAL** - Para valores de categorias (string)
|
||||
2. **NUMERIC** - Para valores numericos (int/float)
|
||||
3. **BOOLEAN** - Para valores verdadeiro/falso
|
||||
|
||||
### Exemplos de Novos Scores
|
||||
|
||||
#### Score de Satisfacao do Usuario
|
||||
|
||||
```python
|
||||
def add_user_satisfaction_score(span, satisfaction_rating):
|
||||
"""
|
||||
Adiciona score de satisfacao do usuario (1-5)
|
||||
"""
|
||||
span.score_trace(
|
||||
name="user_satisfaction",
|
||||
value=satisfaction_rating,
|
||||
data_type="NUMERIC"
|
||||
)
|
||||
```
|
||||
|
||||
#### Score de Tempo de Resposta
|
||||
|
||||
```python
|
||||
import time
|
||||
|
||||
def add_response_time_score(span, start_time):
|
||||
"""
|
||||
Adiciona score de tempo de resposta em segundos
|
||||
"""
|
||||
response_time = time.time() - start_time
|
||||
span.score_trace(
|
||||
name="response_time_seconds",
|
||||
value=response_time,
|
||||
data_type="NUMERIC"
|
||||
)
|
||||
```
|
||||
|
||||
#### Score de Documentos Consultados
|
||||
|
||||
```python
|
||||
def add_documents_used_score(span, num_documents):
|
||||
"""
|
||||
Registra quantos documentos foram consultados
|
||||
"""
|
||||
span.score_trace(
|
||||
name="documents_consulted",
|
||||
value=num_documents,
|
||||
data_type="NUMERIC"
|
||||
)
|
||||
```
|
||||
|
||||
#### Score de Qualidade da Resposta
|
||||
|
||||
```python
|
||||
def add_response_quality_score(span, quality_level):
|
||||
"""
|
||||
Classifica qualidade da resposta
|
||||
Valores: "excellent", "good", "fair", "poor"
|
||||
"""
|
||||
span.score_trace(
|
||||
name="response_quality",
|
||||
value=quality_level,
|
||||
data_type="CATEGORICAL"
|
||||
)
|
||||
```
|
||||
|
||||
#### Score de Feedback Explicito
|
||||
|
||||
```python
|
||||
def add_feedback_score(span, was_helpful):
|
||||
"""
|
||||
Registra se o usuario achou a resposta util
|
||||
"""
|
||||
span.score_trace(
|
||||
name="user_found_helpful",
|
||||
value="True" if was_helpful else "False",
|
||||
data_type="CATEGORICAL"
|
||||
)
|
||||
```
|
||||
|
||||
### Implementacao Completa de Scoring
|
||||
|
||||
```python
|
||||
class LangfuseScorer:
|
||||
"""
|
||||
Classe utilitaria para gerenciar scores do Langfuse
|
||||
"""
|
||||
|
||||
def __init__(self, langfuse_client):
|
||||
self.langfuse = langfuse_client
|
||||
|
||||
def score_interaction(self, span, metrics: dict):
|
||||
"""
|
||||
Adiciona multiplos scores de uma vez
|
||||
|
||||
Args:
|
||||
span: Span atual do Langfuse
|
||||
metrics: Dicionario com metricas
|
||||
{
|
||||
"origem": "web",
|
||||
"email": "user@example.com",
|
||||
"response_time": 2.5,
|
||||
"documents_used": 3,
|
||||
"found_answer": True
|
||||
}
|
||||
"""
|
||||
# Scores categoricos
|
||||
if "origem" in metrics:
|
||||
span.score_trace(name="Origem", value=metrics["origem"], data_type="CATEGORICAL")
|
||||
|
||||
if "email" in metrics:
|
||||
span.score_trace(name="Email", value=metrics["email"], data_type="CATEGORICAL")
|
||||
|
||||
# Scores numericos
|
||||
if "response_time" in metrics:
|
||||
span.score_trace(name="response_time", value=metrics["response_time"], data_type="NUMERIC")
|
||||
|
||||
if "documents_used" in metrics:
|
||||
span.score_trace(name="documents_used", value=metrics["documents_used"], data_type="NUMERIC")
|
||||
|
||||
# Scores booleanos (como categoricos)
|
||||
if "found_answer" in metrics:
|
||||
span.score_trace(
|
||||
name="found_answer",
|
||||
value="True" if metrics["found_answer"] else "False",
|
||||
data_type="CATEGORICAL"
|
||||
)
|
||||
```
|
||||
|
||||
## Visualizando Metricas
|
||||
|
||||
### Acessando o Dashboard
|
||||
|
||||
1. Acesse a interface web do Langfuse: `http://SEU_HOST:3000`
|
||||
2. Navegue ate "Traces" para ver todas as execucoes
|
||||
3. Use filtros por score para analises especificas
|
||||
|
||||
### Queries Uteis
|
||||
|
||||
#### Encontrar conversas sem resposta
|
||||
- Filtrar por: `score.Miss = "True"`
|
||||
|
||||
#### Analise por canal de origem
|
||||
- Agrupar por: `score.Origem`
|
||||
|
||||
#### Metricas de performance
|
||||
- Ordenar por: `score.response_time`
|
||||
|
||||
## Boas Praticas
|
||||
|
||||
### 1. Sempre fazer Flush
|
||||
|
||||
```python
|
||||
# No final de cada execucao
|
||||
langfuse.flush()
|
||||
```
|
||||
|
||||
### 2. Usar Nomes Consistentes
|
||||
|
||||
```python
|
||||
# BOM - nomes consistentes e descritivos
|
||||
span.score_trace(name="user_satisfaction", value=5, data_type="NUMERIC")
|
||||
span.score_trace(name="response_quality", value="good", data_type="CATEGORICAL")
|
||||
|
||||
# EVITAR - nomes inconsistentes
|
||||
span.score_trace(name="sat", value=5, data_type="NUMERIC")
|
||||
span.score_trace(name="Quality", value="good", data_type="CATEGORICAL")
|
||||
```
|
||||
|
||||
### 3. Documentar Valores Possiveis
|
||||
|
||||
Para scores CATEGORICAL, documente os valores possiveis:
|
||||
|
||||
```python
|
||||
# response_quality: "excellent" | "good" | "fair" | "poor"
|
||||
# user_type: "vendor" | "subvendor" | "supervendor" | "support"
|
||||
# channel: "web" | "api" | "whatsapp" | "slack"
|
||||
```
|
||||
|
||||
### 4. Tratar Erros
|
||||
|
||||
```python
|
||||
try:
|
||||
with langfuse.start_as_current_span(name="operation") as span:
|
||||
span.score_trace(name="metric", value=value, data_type="CATEGORICAL")
|
||||
except Exception as e:
|
||||
print(f"Erro ao registrar score: {e}")
|
||||
# Continua execucao sem falhar
|
||||
```
|
||||
|
||||
### 5. Nao Bloquear por Metricas
|
||||
|
||||
```python
|
||||
# Scores nao devem impactar a resposta ao usuario
|
||||
# Se o Langfuse falhar, a conversa deve continuar
|
||||
```
|
||||
|
||||
## Referencias
|
||||
|
||||
- [Documentacao Oficial Langfuse](https://langfuse.com/docs)
|
||||
- [Langfuse Python SDK](https://langfuse.com/docs/sdk/python)
|
||||
- [Integracao LangChain](https://langfuse.com/docs/integrations/langchain)
|
||||
Reference in New Issue
Block a user