@@ -3,7 +3,9 @@ import { InjectRepository } from '@nestjs/typeorm';
33import { Repository } from 'typeorm' ;
44import { Conversation } from 'src/conversations/entities/conversation.entity' ;
55import { User } from 'src/user/user.entity' ;
6+ import { ConfigService } from '@nestjs/config' ;
67import { MessagesService } from 'src/messages/messages.service' ;
8+ import { WizardAPIService } from 'src/wizard/api.wizard.service' ;
79import {
810 ConversationDetailDto ,
911 ConversationMessageMappingDto ,
@@ -16,11 +18,20 @@ import {
1618
1719@Injectable ( )
1820export class ConversationsService {
21+ private readonly wizardApiService : WizardAPIService ;
22+
1923 constructor (
2024 @InjectRepository ( Conversation )
2125 private readonly conversationRepository : Repository < Conversation > ,
2226 private readonly messagesService : MessagesService ,
23- ) { }
27+ private readonly configService : ConfigService ,
28+ ) {
29+ const baseUrl = this . configService . get < string > ( 'OBB_WIZARD_BASE_URL' ) ;
30+ if ( ! baseUrl ) {
31+ throw new Error ( 'Environment variable OBB_WIZARD_BASE_URL is required' ) ;
32+ }
33+ this . wizardApiService = new WizardAPIService ( baseUrl ) ;
34+ }
2435
2536 async create ( namespaceId : string , user : User ) {
2637 const conversation = this . conversationRepository . create ( {
@@ -87,18 +98,51 @@ export class ConversationsService {
8798 return composed ;
8899 }
89100
90- async getFirstContent (
91- userId : string ,
92- conversationId : string ,
93- targetRole : OpenAIMessageRole = OpenAIMessageRole . ASSISTANT ,
94- ) : Promise < string | undefined > {
95- const messages : Message [ ] = await this . compose ( userId , conversationId ) ;
96- for ( const m of messages ) {
97- if ( m . message . role === targetRole && m . message . content ) {
98- return m . message . content ;
101+ async createTitle ( id : string , userId : string ) : Promise < { title : string } > {
102+ const conversation = await this . conversationRepository . findOneOrFail ( {
103+ where : { id, user : { id : userId } } ,
104+ } ) ;
105+ if ( conversation . title ) {
106+ return { title : conversation . title } ;
107+ }
108+ const summary = await this . getSummary ( userId , conversation ) ;
109+ if ( summary . user_content ) {
110+ const content = summary . user_content . trim ( ) ;
111+ if ( content . length > 0 ) {
112+ const titleCreateResponse = await this . wizardApiService . request (
113+ 'POST' ,
114+ '/internal/api/v1/wizard/title' ,
115+ {
116+ text : content ,
117+ } ,
118+ ) ;
119+ conversation . title = titleCreateResponse . title ! ;
120+ await this . conversationRepository . save ( conversation ) ;
121+ return titleCreateResponse as { title : string } ;
99122 }
100123 }
101- return undefined ;
124+ throw new Error ( 'No query content found to create title' ) ;
125+ }
126+
127+ async getSummary (
128+ userId : string ,
129+ c : Conversation ,
130+ ) : Promise < ConversationSummaryDto > {
131+ const messages : Message [ ] = await this . compose ( userId , c . id ) ;
132+ const check = ( m : Message , role : OpenAIMessageRole ) => {
133+ return m . message . role === role && m . message . content ?. trim ( ) ;
134+ } ;
135+ return {
136+ id : c . id ,
137+ title : c . title ,
138+ created_at : c . createdAt . toISOString ( ) ,
139+ updated_at : c . updatedAt ?. toISOString ( ) ,
140+ user_content : messages . find ( ( m ) => check ( m , OpenAIMessageRole . USER ) )
141+ ?. message ?. content ,
142+ assistant_content : messages . find ( ( m ) =>
143+ check ( m , OpenAIMessageRole . ASSISTANT ) ,
144+ ) ?. message ?. content ,
145+ } ;
102146 }
103147
104148 async listSummary (
@@ -110,26 +154,9 @@ export class ConversationsService {
110154 data : ConversationSummaryDto [ ] ;
111155 } > {
112156 const conversations = await this . findAll ( namespaceId , userId , options ) ;
113- const summaries : ConversationSummaryDto [ ] = [ ] ;
114-
115- const check = ( m : Message , role : OpenAIMessageRole ) => {
116- return m . message . role === role && m . message . content ?. trim ( ) ;
117- } ;
118-
119- for ( const c of conversations ) {
120- const messages : Message [ ] = await this . compose ( userId , c . id ) ;
121- summaries . push ( {
122- id : c . id ,
123- title : c . title ,
124- created_at : c . createdAt . toISOString ( ) ,
125- updated_at : c . updatedAt ?. toISOString ( ) ,
126- user_content : messages . find ( ( m ) => check ( m , OpenAIMessageRole . USER ) )
127- ?. message ?. content ,
128- assistant_content : messages . find ( ( m ) =>
129- check ( m , OpenAIMessageRole . ASSISTANT ) ,
130- ) ?. message ?. content ,
131- } as ConversationSummaryDto ) ;
132- }
157+ const summaries : ConversationSummaryDto [ ] = await Promise . all (
158+ conversations . map ( ( c ) => this . getSummary ( userId , c ) ) ,
159+ ) ;
133160 const summariesTotal = await this . countAll ( namespaceId , userId ) ;
134161 return {
135162 data : summaries ,
0 commit comments