我的AI学习 ai维护工具之langfuse

langfuse能系统性维护、测试、监控一个 LLM 应用,主要有如下能力:

  1. 各种指标监控与统计:访问记录、响应时长、Token 用量、计费等等
  2. 调试 Prompt
  3. 测试/验证系统的相关评估指标
  4. 数据集管理(便于回归测试)
  5. Prompt 版本管理(便于升级/回滚)

LangFuse是开源的,支持 LangChain 集成或原生 OpenAI API 集成
官方网站:https://langfuse.com/
项目地址:https://github.com/langfuse
文档地址:https://langfuse.com/docs
API文档:https://api.reference.langfuse.com/
Python SDK: https://python.reference.langfuse.com/

LangFuse中用到的几个基本概念
1. Trace 一般表示用户与系统的一次交互,其中记录输入、输出,也包括自定义的 metadata 比如用户名、session id 等;
2. 一个 trace 内部可以包含多个子过程,这里叫 observarions
3. Observation 可以是多个类型
a.Event 是最基本的单元,用于记录一个 trace 中的每个事件
b.Span 表一个 trace 中的一个"耗时"的过程
c. Generation 是用于记录与 AI 模型交互的 span,例如:调用 embedding 模型、调用 LLM
4.Observation 可以嵌套使用
在这里插入图片描述

要用LangFuse的云服务,首先要在LangFuse官网上注册,注册完后将页面拉倒最后,点免费的SignUp,
在这里插入图片描述
进入后点击Go to project
在这里插入图片描述就到我们的监控页面了,如下
在这里插入图片描述
1. 通过装饰器记录访问大模型的信息
1.1案例 observbe

from langfuse.decorators import observe, langfuse_context
from langfuse.openai import openai # OpenAI integration

# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())

@observe()
def run():
    return openai.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
          {"role": "user", "content": "对我说Hello, World!"}
        ],
    ).choices[0].message.content
 
print(run())
langfuse_context.flush()

@observe()代表要监视的方法,执行后,会在Traceszhong 有一条Trace,如下

在这里插入图片描述

1.2 observe() 装饰器的参数
def observe(
self,
*,
name: Optional[str] = None, # Trace 或 Span 的名称,默认为函数名
as_type: Optional[Literal[‘generation’]] = None, # 将记录定义为 Observation (LLM 调用)
capture_input: bool = True, # 记录输入
capture_output: bool = True, # 记录输出
transform_to_string: Optional[Callable[[Iterable], str]] = None # 将输出转为 string
) -> Callable[[~F], ~F]
1.3 增加observe中的名称

from langfuse.decorators import observe, langfuse_context
from langfuse.openai import openai

@observe(name="HelloWorld")
def run():
    return openai.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
          {"role": "user", "content": "对我说Hello, World!"}
        ],
    ).choices[0].message.content
 
print(run())
langfuse_context.flush()

效果如下
在这里插入图片描述
点击每一条,可以看到输入和输出的内容,运行时间等信息

2.通过 langfuse_context 记录 User ID、Metadata 等

from langfuse.decorators import observe, langfuse_context
from langfuse.openai import openai # OpenAI integration
 
@observe()
def run():
    langfuse_context.update_current_trace(
        name="HelloWorld",
        user_id="wzr",
        tags=["test","demo"]
    )
    return openai.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
          {"role": "user", "content": "对我说Hello, World!"}
        ],
    ).choices[0].message.content
 
print(run())
langfuse_context.flush()

会将user名及Tags写入
在这里插入图片描述

3.通过 LangChain 的回调集成langfuse

del openai
from langchain.prompts import ChatPromptTemplate,HumanMessagePromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnablePassthrough

model = ChatOpenAI(model="gpt-3.5-turbo")

prompt = ChatPromptTemplate.from_messages([HumanMessagePromptTemplate.from_template("Say hello to {input}!")])

# 定义输出解析器
parser = StrOutputParser()

chain = ( {"input": RunnablePassthrough()} | prompt | model | parser)

前面代码时langchain的方法,下面是通过回调和langfuse集成写入到数据库

from langfuse.decorators import langfuse_context, observe

@observe()
def run():
    langfuse_context.update_current_trace(
            name="LangChainTest",
            user_id="lbb",
        )
    
    # 获取当前 LangChain 回调处理器
    langfuse_handler = langfuse_context.get_current_langchain_handler()
    
    return chain.invoke(input="Sysml2", config={"callbacks": [langfuse_handler]})

print(run())
langfuse_context.flush() # Langfuse 回传记录是异步的,可以通过 flush 强制更新

将langfuse_handler事件放到chain中的config中
也支持千帆模型

顺便记录一个计算相似度的方法,就是2调语句的相似度,一般用作比较,超过某一阈值认为2条语句意思一样。

def cos_sim(v, m):
    '''计算cosine相似度'''
    score = np.dot(m, v)/(np.linalg.norm(m, axis=1)*np.linalg.norm(v))
    return score.tolist()

4. 用 Session 记录一个用户的多轮对话

rom langchain_openai import ChatOpenAI
from langchain_core.messages import (
    AIMessage,  # 等价于OpenAI接口中的assistant role
    HumanMessage,  # 等价于OpenAI接口中的user role
    SystemMessage  # 等价于OpenAI接口中的system role
)
from datetime import datetime
from langfuse.decorators import langfuse_context, observe

now = datetime.now()

llm = ChatOpenAI()

messages = [SystemMessage(content="你是课程助理。"),]
session_id = "chat-"+now.strftime("%d/%m/%Y %H:%M:%S")

@observe()
def chat_one_turn(user_input, user_id, turn_id):
    langfuse_context.update_current_trace(
        name=f"ChatTurn{turn_id}",
        user_id=user_id,
        session_id=session_id
    )
    langfuse_handler = langfuse_context.get_current_langchain_handler()
    messages.append(HumanMessage(content=user_input))
    response = llm.invoke(messages, config={"callbacks": [langfuse_handler]})
    messages.append(response)
    return response.content  

user_id="lbb"
turn_id = 0
while True:
    user_input = input("User: ")
    if user_input.strip() == "":
        break
    reply = chat_one_turn(user_input, user_id, turn_id)
    print("AI: "+reply)
    turn_id += 1
    langfuse_context.flush() 

执行如下
在这里插入图片描述
与 LlamaIndex 集成

from llama_index.core import Settings
from llama_index.core.callbacks import CallbackManager
from langfuse.llama_index import LlamaIndexCallbackHandler

# 定义 LangFuse 的 CallbackHandler
langfuse_callback_handler = LlamaIndexCallbackHandler()

# 修改 LlamaIndex 的全局设定
Settings.callback_manager = CallbackManager([langfuse_callback_handler])

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
from llama_index.readers.file import PyMuPDFReader
from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding

# 指定全局llm与embedding模型
Settings.llm = OpenAI(temperature=0, model="gpt-4o")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small", dimensions=512)
Settings.transforms = [SentenceSplitter(chunk_size=300, chunk_overlap=100)]

# 加载 pdf 文档
documents = SimpleDirectoryReader("./data", file_extractor={".pdf": PyMuPDFReader()}).load_data()

# 指定 Vector Store 用于 index
index = VectorStoreIndex.from_documents(documents)

# 构建单轮 query engine
query_engine = index.as_query_engine()

response = query_engine.query("llama2有多少参数")

print(response)

执行llamindex时应用全局设定Setting。
Settings.callback_manager
Settings.llm
Settings.embed_model
Settings.transforms
其中Settings.callback_manager将执行日志写入到langfuse中

LangSmith:目前只支持Open|AI,所以在这里就不介绍了

### Langfuse SSO Integration Guide #### Overview of Single Sign-On (SSO) Single Sign-On (SSO) allows users to access multiple applications and services using a single set of credentials, enhancing both security and user convenience. For integrating SSO into platforms like Langfuse, the process involves configuring authentication mechanisms that can securely verify user identities across different systems. Langfuse supports various methods for implementing SSO through third-party identity providers or custom solutions depending on specific requirements[^1]. #### Prerequisites for Integrating SSO with Langfuse Before starting the integration: - Ensure an active subscription plan supporting advanced features such as SSO. - Obtain necessary details from your Identity Provider (IdP), including metadata URL, entity ID, etc. - Decide which protocol will be used—commonly OAuth 2.0, OpenID Connect, or SAML 2.0—for communication between Langfuse and IdP. #### Configuration Steps within Langfuse Platform To configure SSO inside Langfuse: Navigate to **Admin Settings**, select **Security & Authentication**, then choose **Single Sign-On** option where one could specify settings related to chosen protocols mentioned earlier. Afterward, input relevant information provided by IdP according to selected standards. For instance, when opting for SAML-based setup: ```xml <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_abcde..." Version="2.0"> <!-- Other elements --> </samlp:AuthnRequest> ``` Or if preferring OIDC flow: ```json { "client_id": "...", "redirect_uris": ["https://yourapp.com/callback"], ... } ``` After completing configuration changes, test thoroughly ensuring seamless interaction without errors during login attempts via external IdPs. #### Troubleshooting Common Issues During Setup If encountering issues while setting up SSO functionality: - Verify network connectivity is stable since intermittent disruptions may cause failures in obtaining tokens required for successful logins. - Check expiration status of any involved tokens; clearing caches followed by re-authentication might resolve temporary glitches caused by stale data [^2]. - Confirm consistency among all configured endpoints regarding supported protocols preventing mismatches leading to unsuccessful authentications. By following these guidelines carefully, organizations should achieve smooth implementation of robust SSO capabilities tailored specifically towards their needs utilizing Langfuse's flexible infrastructure. --related questions-- 1. What are some best practices for securing SSO implementations? 2. How does Langfuse handle multi-factor authentication alongside traditional username/password combinations? 3. Can you provide examples of popular Identity Providers compatible with Langfuse’s SSO feature? 4. In what scenarios would choosing CAS over other options benefit my organization most effectively? 5. Are there additional costs associated with enabling enterprise-grade SSO support on Langfuse?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值