From feefeb44d7dedab322980097eff000f566eb2779 Mon Sep 17 00:00:00 2001 From: "Charlie.Wei" Date: Sun, 8 Sep 2024 13:25:27 +0800 Subject: [PATCH] fix LangSmith project config error (#7996) --- .../ops/langsmith_trace/langsmith_trace.py | 23 ++++++++++++++++++ api/core/ops/ops_trace_manager.py | 13 ++++++++++ api/services/ops_service.py | 24 +++++++++++++++---- .../overview/tracing/provider-panel.tsx | 7 +++--- 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/api/core/ops/langsmith_trace/langsmith_trace.py b/api/core/ops/langsmith_trace/langsmith_trace.py index cc242905bd..9cbc805fe7 100644 --- a/api/core/ops/langsmith_trace/langsmith_trace.py +++ b/api/core/ops/langsmith_trace/langsmith_trace.py @@ -1,9 +1,11 @@ import json import logging import os +import uuid from datetime import datetime, timedelta from langsmith import Client +from langsmith.schemas import RunBase from core.ops.base_trace_instance import BaseTraceInstance from core.ops.entities.config_entity import LangSmithConfig @@ -371,3 +373,24 @@ class LangSmithDataTrace(BaseTraceInstance): except Exception as e: logger.debug(f"LangSmith API check failed: {str(e)}") raise ValueError(f"LangSmith API check failed: {str(e)}") + + def get_project_url(self): + try: + run_data = RunBase( + id=uuid.uuid4(), + name="tool", + inputs={"input": "test"}, + outputs={"output": "test"}, + run_type=LangSmithRunType.tool, + start_time=datetime.now(), + ) + + project_url = self.langsmith_client.get_run_url(run=run_data, + project_id=self.project_id, + project_name=self.project_name) + return project_url.split('/r/')[0] + except Exception as e: + logger.debug(f"LangSmith get run url failed: {str(e)}") + raise ValueError(f"LangSmith get run url failed: {str(e)}") + + diff --git a/api/core/ops/ops_trace_manager.py b/api/core/ops/ops_trace_manager.py index 1416d6bd2d..aefab6ed16 100644 --- a/api/core/ops/ops_trace_manager.py +++ b/api/core/ops/ops_trace_manager.py @@ -264,6 +264,19 @@ class OpsTraceManager: tracing_config = config_type(**tracing_config) return trace_instance(tracing_config).get_project_key() + @staticmethod + def get_trace_config_project_url(tracing_config: dict, tracing_provider: str): + """ + get trace config is project key + :param tracing_config: tracing config + :param tracing_provider: tracing provider + :return: + """ + config_type, trace_instance = provider_config_map[tracing_provider]['config_class'], \ + provider_config_map[tracing_provider]['trace_instance'] + tracing_config = config_type(**tracing_config) + return trace_instance(tracing_config).get_project_url() + class TraceTask: def __init__( diff --git a/api/services/ops_service.py b/api/services/ops_service.py index 35aa6817e1..1e7935d299 100644 --- a/api/services/ops_service.py +++ b/api/services/ops_service.py @@ -32,7 +32,15 @@ class OpsService: "project_key" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_key") ): project_key = OpsTraceManager.get_trace_config_project_key(decrypt_tracing_config, tracing_provider) - new_decrypt_tracing_config.update({"project_key": project_key}) + new_decrypt_tracing_config.update( + {"project_url": "{host}/project/{key}".format(host=decrypt_tracing_config.get("host"), key=project_key)} + ) + + if tracing_provider == "langsmith" and ( + "project_url" not in decrypt_tracing_config or not decrypt_tracing_config.get("project_url") + ): + project_url = OpsTraceManager.get_trace_config_project_url(decrypt_tracing_config, tracing_provider) + new_decrypt_tracing_config.update({"project_url": project_url}) trace_config_data.tracing_config = new_decrypt_tracing_config return trace_config_data.to_dict() @@ -62,8 +70,14 @@ class OpsService: if not OpsTraceManager.check_trace_config_is_effective(tracing_config, tracing_provider): return {"error": "Invalid Credentials"} - # get project key - project_key = OpsTraceManager.get_trace_config_project_key(tracing_config, tracing_provider) + # get project url + if tracing_provider == "langfuse": + project_key = OpsTraceManager.get_trace_config_project_key(tracing_config, tracing_provider) + project_url = "{host}/project/{key}".format(host=tracing_config.get("host"), key=project_key) + elif tracing_provider == "langsmith": + project_url = OpsTraceManager.get_trace_config_project_url(tracing_config, tracing_provider) + else: + project_url = None # check if trace config already exists trace_config_data: TraceAppConfig = ( @@ -78,8 +92,8 @@ class OpsService: # get tenant id tenant_id = db.session.query(App).filter(App.id == app_id).first().tenant_id tracing_config = OpsTraceManager.encrypt_tracing_config(tenant_id, tracing_provider, tracing_config) - if tracing_provider == "langfuse" and project_key: - tracing_config["project_key"] = project_key + if project_url: + tracing_config["project_url"] = project_url trace_config_data = TraceAppConfig( app_id=app_id, tracing_provider=tracing_provider, diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx index b908322a92..6e5046ecf8 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-panel.tsx @@ -48,9 +48,10 @@ const ProviderPanel: FC = ({ e.preventDefault() e.stopPropagation() - const url = `${config?.host}/project/${config?.project_key}` - window.open(url, '_blank', 'noopener,noreferrer') - }, []) + const url = config?.project_url + if (url) + window.open(url, '_blank', 'noopener,noreferrer') + }, [config?.project_url]) const handleChosen = useCallback((e: React.MouseEvent) => { e.stopPropagation()