Skip to content

langchain callback improve message init #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 10, 2025
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
4 changes: 2 additions & 2 deletions cozeloop/integration/langchain/trace_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ def _span_type_mapping(span_type: str) -> str:
elif span_type == 'ReActSingleInputOutputParser':
return 'parser'
elif span_type == 'tool':
return 'plugin'
return 'tool'
return span_type


Expand Down Expand Up @@ -406,7 +406,7 @@ def _convert_inputs(inputs: Any) -> Any:
format_inputs['content'] = inputs.content
return format_inputs
if isinstance(inputs, BaseMessage):
message = Message(role=inputs.type, content=inputs.content)
message = Message(role=inputs.type, content=inputs.content, tool_calls=inputs.additional_kwargs.get('tool_calls', []))
return message
if isinstance(inputs, ChatPromptValue):
return _convert_inputs(inputs.messages)
Expand Down
25 changes: 18 additions & 7 deletions cozeloop/integration/langchain/trace_model/llm_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import json
import time
from typing import List, Optional, Union
from typing import List, Optional, Union, Dict, Any
from pydantic.dataclasses import dataclass
from langchain_core.messages import BaseMessage, ToolMessage, AIMessageChunk
from langchain_core.outputs import Generation, ChatGeneration
Expand All @@ -14,7 +14,7 @@ class ToolFunction:
name: Optional[str] = None
description: Optional[str] = None
parameters: Optional[dict] = None
arguments: Optional[dict] = None
arguments: Optional[Union[dict, str]] = None


@dataclass
Expand Down Expand Up @@ -50,20 +50,31 @@ class Message:
tool_calls: List[ToolCall] = None

def __post_init__(self):
if self.role is not None and self.role == 'AIMessageChunk':
if self.role is not None and (self.role == 'AIMessageChunk' or self.role == 'ai'):
self.role = 'assistant'
parts: Optional[List[Parts]] = []
if isinstance(self.content, List) and all(isinstance(x, dict) for x in self.content):
is_parts = False
for each in self.content:
text = each.get('text', None)
url = each.get('url', each.get('image_url', {}).get('url', None))
if text is None and url is None:
continue
is_parts = True
parts.append(Parts(type=each.get('type', ''), text=text, image_url=ImageUrl(url=url) if url is not None else None))
self.content = None
if is_parts:
self.content = None
else:
self.content = self.content.__str__()
elif isinstance(self.content, dict):
is_part = False
text = self.content.get('text', None)
url = self.content.get('url', self.content.get('image_url', {}).get('url', None))
parts.append(Parts(type=self.content.get('type', ''), text=text, image_url=ImageUrl(url=url) if url is not None else None))
self.content = None
if text is not None or url is not None:
parts.append(Parts(type=self.content.get('type', ''), text=text, image_url=ImageUrl(url=url) if url is not None else None))
self.content = None
else:
self.content = self.content.__str__()
elif isinstance(self.content, List) and all(type(x, Parts) for x in self.content):
parts = self.content
self.content = None
Expand Down Expand Up @@ -172,4 +183,4 @@ def convert_tool_calls(tool_calls: list) -> List[ToolCall]:
for tool_call in tool_calls:
function = ToolFunction(name=tool_call.get('function', {}).get('name', ''), arguments=json.loads(tool_call.get('function', {}).get('arguments', {})))
format_tool_calls.append(ToolCall(id=tool_call.get('id', ''), type=tool_call.get('type', ''), function=function))
return format_tool_calls
return format_tool_calls
8 changes: 4 additions & 4 deletions cozeloop/integration/langchain/trace_model/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import importlib.metadata as metadata
from typing import Optional, Any

from cozeloop.spec import tracespce
from cozeloop.spec import tracespec


class RuntimeInfo(tracespce.Runtime):
language: Optional[str] = tracespce.V_LANG_PYTHON
library: Optional[str] = tracespce.V_LIB_LANGCHAIN
class RuntimeInfo(tracespec.Runtime):
language: Optional[str] = tracespec.V_LANG_PYTHON
library: Optional[str] = tracespec.V_LIB_LANGCHAIN

def model_post_init(self, context: Any) -> None:
try:
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/consts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from contextvars import ContextVar

from .error import *
from ...spec.tracespce.span_key import INPUT_TOKENS, OUTPUT_TOKENS, TOKENS, INPUT, OUTPUT
from ...spec.tracespec.span_key import INPUT_TOKENS, OUTPUT_TOKENS, TOKENS, INPUT, OUTPUT

# default values for loop client
# ComBaseURL = "https://api.coze.com"
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/prompt/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from typing import List, Dict

from cozeloop.spec.tracespce import PromptInput, PromptOutput, ModelMessage, PromptArgument
from cozeloop.spec.tracespec import PromptInput, PromptOutput, ModelMessage, PromptArgument
from cozeloop.entities.prompt import (
Prompt as EntityPrompt,
Message as EntityMessage,
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/prompt/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from jinja2 import Environment, BaseLoader, Undefined
from jinja2.utils import missing, object_type_repr

from cozeloop.spec.tracespce import PROMPT_KEY, INPUT, PROMPT_VERSION, V_SCENE_PROMPT_TEMPLATE, V_SCENE_PROMPT_HUB
from cozeloop.spec.tracespec import PROMPT_KEY, INPUT, PROMPT_VERSION, V_SCENE_PROMPT_TEMPLATE, V_SCENE_PROMPT_HUB
from cozeloop.entities.prompt import (Prompt, Message, VariableDef, VariableType, TemplateType, Role,
PromptVariable)
from cozeloop.internal import consts
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/trace/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import time
from typing import Dict, List, Optional, Tuple, Callable, Any

from cozeloop.spec.tracespce import ModelInput, ModelMessagePart, ModelMessagePartType, ModelImageURL, ModelFileURL, ModelOutput
from cozeloop.spec.tracespec import ModelInput, ModelMessagePart, ModelMessagePartType, ModelImageURL, ModelFileURL, ModelOutput
from cozeloop.internal.consts import *
from cozeloop.internal.httpclient import Client, BaseResponse
from cozeloop.internal.trace.model.model import UploadType, Attachment, ObjectStorage
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/trace/noop_span.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from cozeloop.entities.prompt import Prompt
from cozeloop.span import Span
from cozeloop.spec.tracespce import Runtime
from cozeloop.spec.tracespec import Runtime


class NoopSpan(Span, ABC):
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/trace/span.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import urllib.parse

from cozeloop import span
from cozeloop.spec.tracespce import (ModelInput, ModelOutput, ModelMessagePartType, ModelMessage, ModelMessagePart,
from cozeloop.spec.tracespec import (ModelInput, ModelOutput, ModelMessagePartType, ModelMessage, ModelMessagePart,
ModelImageURL, ModelFileURL, ModelChoice, Runtime, ERROR, PROMPT_KEY,
PROMPT_VERSION, MODEL_PROVIDER, MODEL_NAME, RUNTIME_, CALL_OPTIONS,
V_SCENE_CUSTOM, V_LANG_PYTHON)
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/internal/trace/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from datetime import datetime
from typing import Dict, Optional

from cozeloop.spec.tracespce import Runtime, RUNTIME_
from cozeloop.spec.tracespec import Runtime, RUNTIME_
from cozeloop.internal import consts
from cozeloop.internal.trace.span import from_header, Span, SpanContext, \
get_newest_span_from_context, set_span_to_context, logger
Expand Down
2 changes: 1 addition & 1 deletion cozeloop/span.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Dict, Any
from datetime import datetime
from cozeloop.entities.prompt import Prompt
from cozeloop.spec.tracespce import Runtime
from cozeloop.spec.tracespec import Runtime


class SpanContext(ABC):
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from pydantic import BaseModel

from cozeloop.spec.tracespce import ModelMessage
from cozeloop.spec.tracespec import ModelMessage


class PromptInput(BaseModel):
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/prompt/prompt_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import cozeloop
from cozeloop import Message
from cozeloop.entities.prompt import Role
from cozeloop.spec.tracespce import CALL_OPTIONS, ModelCallOption, ModelMessage, ModelInput
from cozeloop.spec.tracespec import CALL_OPTIONS, ModelCallOption, ModelMessage, ModelInput


class LLMRunner:
Expand Down
2 changes: 1 addition & 1 deletion examples/trace/multi_modality.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from typing import Any

from cozeloop import new_client
from cozeloop.spec.tracespce import ModelInput, ModelMessage, ModelMessagePart, ModelMessagePartType, ModelImageURL, ModelFileURL
from cozeloop.spec.tracespec import ModelInput, ModelMessage, ModelMessagePart, ModelMessagePartType, ModelImageURL, ModelFileURL
from cozeloop.logger import set_log_level

logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion examples/trace/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from cozeloop.internal.consts import TRACE_PROMPT_HUB_SPAN_NAME, TRACE_PROMPT_TEMPLATE_SPAN_NAME
from cozeloop.entities.prompt import PromptTemplate, Prompt, Message, Role
from cozeloop import new_client, set_log_level
from cozeloop.spec.tracespce import ModelMessage, PromptInput, PromptArgument, V_PROMPT_HUB_SPAN_TYPE, PROMPT_KEY, \
from cozeloop.spec.tracespec import ModelMessage, PromptInput, PromptArgument, V_PROMPT_HUB_SPAN_TYPE, PROMPT_KEY, \
INPUT, PROMPT_VERSION, OUTPUT, V_PROMPT_SPAN_TYPE


Expand Down