Skip to content

messageProcessor 消息处理工具

messageProcessor 是一套用于处理聊天消息和工具调用的实用工具函数集合,主要用于格式化消息内容、处理工具属性和对消息部分进行排序。

安装和导入

typescript
import {
  formatPart,
  getToolProps,
  sortedUserMessageParts,
} from "@pt/common-ui/utils";

API 文档

formatPart

格式化消息部分,将消息对象转换为可显示的文本格式。

类型签名

typescript
function formatPart(part: any): string;

参数

  • part (any): 消息部分对象,包含消息的类型和内容信息

返回值

  • string: 格式化后的文本内容

示例

typescript
// 文本类型消息
const textPart = {
  type: "text",
  text: "Hello, world!",
};

const formattedText = formatPart(textPart);
console.log(formattedText); // "Hello, world!"

// 其他类型消息
const otherPart = {
  type: "image",
  text: "Image description",
};

const formattedOther = formatPart(otherPart);
console.log(formattedOther); // "Image description"

getToolProps

获取工具组件的属性对象,用于处理工具调用和结果的映射关系。

类型签名

typescript
function getToolProps(
  part: any,
  parts: any,
  config: { message_id: string }
): object;

参数

  • part (any): 当前工具部分对象
  • parts (any): 所有消息部分的数组
  • config (object): 配置对象
    • message_id (string): 消息 ID

返回值

  • object: 工具组件的属性对象

特殊处理

对于 PtArtifact 类型的工具,返回特定的属性结构:

typescript
{
  identifier: string,
  type: string,
  content: string,
  title: string,
  language: string,
  isClose: boolean
}

对于其他工具类型,返回:

typescript
{
  part: {
    ...part,
    result: any
  }
}

示例

typescript
// PtArtifact 工具示例
const artifactPart = {
  name: "PtArtifact",
  id: "tool_123",
  input: {
    type: "code",
    identifier: "example-code",
    content: "console.log('Hello');",
    title: "示例代码",
    language: "javascript",
  },
  input_raw: "raw_data",
};

const allParts = [artifactPart];
const config = { message_id: "msg_456" };

const props = getToolProps(artifactPart, allParts, config);
console.log(props);
// {
//   identifier: "example-code",
//   type: "code",
//   content: "console.log('Hello');",
//   title: "示例代码",
//   language: "javascript",
//   isClose: false
// }

// 普通工具示例
const normalTool = {
  name: "search",
  id: "tool_789",
  input: { query: "Vue.js" },
};

const toolResult = {
  type: "tool_result",
  name: "search",
  tool_use_id: "tool_789",
  content: "搜索结果...",
};

const partsWithResult = [normalTool, toolResult];

const normalProps = getToolProps(normalTool, partsWithResult, config);
console.log(normalProps);
// {
//   part: {
//     name: "search",
//     id: "tool_789",
//     input: { query: "Vue.js" },
//     result: {
//       type: "tool_result",
//       name: "search",
//       tool_use_id: "tool_789",
//       content: "搜索结果..."
//     }
//   }
// }

sortedUserMessageParts

对用户消息部分进行排序,确保文本类型的消息部分排在前面。

类型签名

typescript
function sortedUserMessageParts(parts: any[]): any[];

参数

  • parts (any[]): 消息部分数组

返回值

  • any[]: 排序后的消息部分数组

排序规则

  • 文本类型 (type: "text") 的消息部分排在前面
  • 非文本类型的消息部分排在后面
  • 相同类型内部保持原有顺序

示例

typescript
const messageParts = [
  {
    type: "image",
    content: "图片内容",
  },
  {
    type: "text",
    text: "这是文本消息",
  },
  {
    type: "tool_use",
    name: "calculator",
  },
  {
    type: "text",
    text: "另一条文本消息",
  },
];

const sorted = sortedUserMessageParts(messageParts);
console.log(sorted);
// [
//   { type: "text", text: "这是文本消息" },
//   { type: "text", text: "另一条文本消息" },
//   { type: "image", content: "图片内容" },
//   { type: "tool_use", name: "calculator" }
// ]

使用场景

聊天消息渲染

typescript
import {
  formatPart,
  sortedUserMessageParts,
} from "@pt/common-ui/utils";

// 渲染用户消息
function renderUserMessage(messageParts: any[]) {
  const sortedParts = sortedUserMessageParts(messageParts);

  return sortedParts
    .map((part) => {
      if (part.type === "text") {
        return formatPart(part);
      }
      // 处理其他类型的消息部分
      return `[${part.type}]: ${formatPart(part)}`;
    })
    .join("\n");
}

工具组件属性处理

typescript
import { getToolProps } from "@pt/common-ui/utils";

// 在 Vue 组件中使用
export default {
  props: ["toolPart", "allParts", "messageId"],
  computed: {
    toolComponentProps() {
      return getToolProps(this.toolPart, this.allParts, {
        message_id: this.messageId,
      });
    },
  },
  template: `
    <ToolComponent v-bind="toolComponentProps" />
  `,
};

消息预处理管道

typescript
import {
  formatPart,
  getToolProps,
  sortedUserMessageParts,
} from "@pt/common-ui/utils";

class MessageProcessor {
  static processMessage(message: any) {
    // 1. 对消息部分进行排序
    const sortedParts = sortedUserMessageParts(message.parts);

    // 2. 格式化文本部分
    const textParts = sortedParts
      .filter((part) => part.type === "text")
      .map((part) => formatPart(part));

    // 3. 处理工具部分
    const toolParts = sortedParts
      .filter((part) => part.type === "tool_use")
      .map((part) =>
        getToolProps(part, sortedParts, { message_id: message.id })
      );

    return {
      text: textParts.join(" "),
      tools: toolParts,
      originalParts: sortedParts,
    };
  }
}

// 使用示例
const message = {
  id: "msg_123",
  parts: [
    {
      type: "tool_use",
      name: "PtArtifact",
      id: "tool_1",
      input: { type: "code", content: 'console.log("test");' },
    },
    { type: "text", text: "这是一段代码示例" },
    { type: "text", text: "请查看上面的代码" },
  ],
};

const processed = MessageProcessor.processMessage(message);
console.log(processed);

最佳实践

1. 类型安全

建议在 TypeScript 项目中定义明确的类型接口:

typescript
interface MessagePart {
  type: "text" | "tool_use" | "tool_result" | "image";
  text?: string;
  name?: string;
  id?: string;
  input?: any;
  content?: any;
}

interface ToolConfig {
  message_id: string;
}

// 使用类型化的函数
function typedFormatPart(part: MessagePart): string {
  return formatPart(part);
}

2. 错误处理

在生产环境中添加适当的错误处理:

typescript
function safeFormatPart(part: any): string {
  try {
    return formatPart(part);
  } catch (error) {
    console.warn("格式化消息部分时出错:", error);
    return "[无法显示的内容]";
  }
}

function safeGetToolProps(part: any, parts: any, config: any): any {
  try {
    return getToolProps(part, parts, config);
  } catch (error) {
    console.warn("获取工具属性时出错:", error);
    return { part: { ...part, error: true } };
  }
}

3. 性能优化

对于大量消息的处理,考虑使用缓存和批处理:

typescript
class OptimizedMessageProcessor {
  private static cache = new Map();

  static processMessages(messages: any[]) {
    return messages.map((message) => {
      const cacheKey = `${message.id}_${message.timestamp}`;

      if (this.cache.has(cacheKey)) {
        return this.cache.get(cacheKey);
      }

      const processed = MessageProcessor.processMessage(message);
      this.cache.set(cacheKey, processed);

      return processed;
    });
  }
}

注意事项

  1. 输入验证: 这些函数接受 any 类型参数,在生产环境中建议添加输入验证
  2. PtArtifact 特殊处理: getToolProps() 对 PtArtifact 工具有特殊的处理逻辑
  3. 排序稳定性: sortedUserMessageParts() 保持相同类型消息的原有顺序
  4. 内存使用: 处理大量消息时注意内存使用,考虑实现分页或虚拟滚动

相关文档

Released under the MIT License.