ChatMessage.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Database\Eloquent\Collection;
  4. use Illuminate\Database\Eloquent\Factories\HasFactory;
  5. use Illuminate\Database\Eloquent\Model;
  6. use Illuminate\Support\Str;
  7. class ChatMessage extends Model
  8. {
  9. use HasFactory;
  10. protected $fillable = [
  11. 'uid',
  12. 'chat_id',
  13. 'parent_id',
  14. 'session_id',
  15. 'role',
  16. 'content',
  17. 'model_name',
  18. 'tool_calls',
  19. 'tool_call_id',
  20. 'is_active',
  21. ];
  22. protected $dates = [
  23. 'deleted_at',
  24. ];
  25. protected $casts = [
  26. 'id' => 'string',
  27. 'tool_calls' => 'array',
  28. 'is_active' => 'boolean',
  29. 'created_at' => 'datetime',
  30. 'updated_at' => 'datetime',
  31. 'deleted_at' => 'datetime',
  32. ];
  33. protected static function boot()
  34. {
  35. parent::boot();
  36. static::creating(function ($model) {
  37. if (empty($model->uid)) {
  38. $model->uid = (string) Str::uuid();
  39. }
  40. if (empty($model->session_id)) {
  41. $model->session_id = (string) Str::uuid();
  42. }
  43. });
  44. }
  45. /**
  46. * 关联聊天
  47. */
  48. public function chat()
  49. {
  50. return $this->belongsTo(Chat::class);
  51. }
  52. /**
  53. * 关联父消息
  54. */
  55. public function parent()
  56. {
  57. return $this->belongsTo(ChatMessage::class, 'parent_id', 'uid');
  58. }
  59. /**
  60. * 关联子消息
  61. */
  62. public function children()
  63. {
  64. return $this->hasMany(ChatMessage::class, 'parent_id', 'uid');
  65. }
  66. /**
  67. * 关联激活状态的子消息
  68. */
  69. public function activeChildren()
  70. {
  71. return $this->hasMany(ChatMessage::class, 'parent_id', 'uid')
  72. ->where('is_active', true);
  73. }
  74. /**
  75. * Scope: 只查询激活状态的消息
  76. */
  77. public function scopeActive($query)
  78. {
  79. return $query->where('is_active', true);
  80. }
  81. /**
  82. * Scope: 根据角色查询
  83. */
  84. public function scopeByRole($query, string $role)
  85. {
  86. return $query->where('role', $role);
  87. }
  88. /**
  89. * Scope: 根据会话ID查询
  90. */
  91. public function scopeBySession($query, string $sessionId)
  92. {
  93. return $query->where('session_id', $sessionId);
  94. }
  95. /**
  96. * Scope: 根据聊天ID查询
  97. */
  98. public function scopeByChat($query, string $chatId)
  99. {
  100. return $query->where('chat_id', $chatId);
  101. }
  102. /**
  103. * 获取消息路径(从根到当前消息)
  104. */
  105. public function getPath(): array
  106. {
  107. $path = [];
  108. $current = $this;
  109. while ($current) {
  110. array_unshift($path, $current);
  111. $current = $current->parent;
  112. }
  113. return $path;
  114. }
  115. /**
  116. * 获取消息树的所有叶子节点
  117. */
  118. public function getLeaves(): Collection
  119. {
  120. return ChatMessage::where('chat_id', $this->chat_id)
  121. ->whereNotNull('parent_id')
  122. ->whereDoesntHave('children')
  123. ->get();
  124. }
  125. /**
  126. * 获取Token使用情况
  127. */
  128. public function getTokenUsage(): ?array
  129. {
  130. return $this->metadata['token_usage'] ?? null;
  131. }
  132. /**
  133. * 获取生成参数
  134. */
  135. public function getGenerationParams(): ?array
  136. {
  137. return $this->metadata['generation_params'] ?? null;
  138. }
  139. /**
  140. * 设置Token使用情况
  141. */
  142. public function setTokenUsage(array $tokenUsage): void
  143. {
  144. $metadata = $this->metadata ?? [];
  145. $metadata['token_usage'] = $tokenUsage;
  146. $this->update(['metadata' => $metadata]);
  147. }
  148. /**
  149. * 设置生成参数
  150. */
  151. public function setGenerationParams(array $params): void
  152. {
  153. $metadata = $this->metadata ?? [];
  154. $metadata['generation_params'] = $params;
  155. $this->update(['metadata' => $metadata]);
  156. }
  157. public function siblings()
  158. {
  159. return $this->where('parent_id', $this->parent_id)
  160. ->where('role', $this->role)
  161. ->where('id', '!=', $this->id);
  162. }
  163. public function getRouteKeyName()
  164. {
  165. return 'uid';
  166. }
  167. }