@@ -28,15 +28,19 @@ interface
2828 PRINTLN_TOOL_CALLING = 7 , // print a whole line: tool calling (supported by only a few models)
2929 PRINTLN_EMBEDDING = 8 , // print a whole line: embedding (example: "0.1,0.3,...")
3030 PRINTLN_RANKING = 9 , // print a whole line: ranking (example: "0.8")
31- PRINTLN_TOKEN_IDS =10 // print a whole line: token ids (example: "1,3,5,8,...")
31+ PRINTLN_TOKEN_IDS =10 , // print a whole line: token ids (example: "1,3,5,8,...")
3232 PRINTLN_LOGGING =11 , // print a whole line: internal logging with the first char indicating level
3333 // (space): None; D: Debug; I: Info; W: Warn; E: Error; .: continue
3434 PRINTLN_BEAM_SEARCH =12 , // print a whole line: a result of beam search with a prefix of probability
3535 // (example: "0.8,....")
36- PRINTLN_MODEL_INFO =13 , // when a model is started, print a whole line of basic model information (json format)
36+ PRINTLN_MODEL_INFO =13 , // when a model is started, print a whole line of basic model information (json format)
3737 // (example: {"name": "llama", "context_length": 100, "capabilities": [text, ...], ...})
38+ PRINT_THOUGHT_CHUNK =14 , // same as PRINT_CHAT_CHUNK, but this from "thoughts".
39+ // possible leading or trailing tags (such as <think>, </think>) are removed.
40+ // use `+detect_thoughts` to enable this.
3841
39- PRINT_EVT_ASYNC_COMPLETED = 100 , // last async operation completed (utf8_str is null)
42+ PRINT_EVT_ASYNC_COMPLETED = 100 , // last async operation completed (utf8_str is null)
43+ PRINT_EVT_THOUGHT_COMPLETED = 101 // thought completed
4044 );
4145
4246 TChatLLMPrint = procedure(UserData: Pointer; APrintType: Integer; AUTF8Str: PAnsiChar); cdecl;
@@ -104,6 +108,17 @@ interface
104108 }
105109 function ChatLLMUserInput (Obj: PChatLLMObj; AUTF8Str: PAnsiChar): Integer; stdcall; external CHATLLMLIB name ' chatllm_user_input' ;
106110
111+ {
112+ @brief set prefix for AI generation
113+
114+ This prefix is used in all following rounds..
115+
116+ @param[in] obj model object
117+ @param[in] utf8_str prefix
118+ @return 0 if succeeded
119+ }
120+ function ChatLLMSetAIPrefix (Obj: PChatLLMObj; AUTF8Str: PAnsiChar): Integer; stdcall; external CHATLLMLIB name ' chatllm_set_ai_prefix' ;
121+
107122 {
108123 @brief tool input
109124
@@ -178,7 +193,7 @@ interface
178193 @param[in] name vector store name
179194 @return 0 if succeeded
180195 }
181- function ChatLLMRAGSelectStore (Obj: PChatLLMObj; AUTF8StrQ, AUTF8StrA : PAnsiChar): Integer; stdcall; external CHATLLMLIB name ' chatllm_rag_select_store' ;
196+ function ChatLLMRAGSelectStore (Obj: PChatLLMObj; AName : PAnsiChar): Integer; stdcall; external CHATLLMLIB name ' chatllm_rag_select_store' ;
182197
183198 {
184199 @brief abort generation
@@ -234,6 +249,11 @@ interface
234249 TChatLLM = class
235250 private
236251 FObj: PChatLLMObj;
252+ FOnThoughtChunk: TLLMPrintEvent;
253+ FOnThoughtEnded: TNotifyEvent;
254+ FOutputAcc: string;
255+ FThoughtAcc: string;
256+ FReferences: TStringList;
237257 FMetaAcc: string;
238258 FMiscResult: string;
239259 FOnPrintHistoryAI: TLLMPrintEvent;
@@ -249,6 +269,10 @@ TChatLLM = class
249269 FOnStateChanged: TLLMStateChangedEvent;
250270 FOnTextEmbeddingResult: TLLMTextEmbeddingResult;
251271 FOnQARankingResult: TLLMQARankingResult;
272+ FAutoAbortSufffix: string;
273+ FCallingMode: Boolean;
274+ FCallResult: TLLMPrintEvent;
275+ FModelInfo: string;
252276 function GetBusy : Boolean;
253277 procedure SetOnChunk (const Value : TLLMPrintEvent);
254278 procedure SetOnPrintError (const Value : TLLMPrintEvent);
@@ -259,17 +283,25 @@ TChatLLM = class
259283 procedure SetOnPrintRewrittenQuery (const Value : TLLMPrintEvent);
260284 procedure SetOnPrintToolCalling (const Value : TLLMPrintEvent);
261285 procedure SetGenMaxTokens (const Value : Integer);
262- procedure HandlePrint (APrintType: Integer; S: string);
263- procedure HandleEnd ;
264286 procedure SetOnGenerationEnded (const Value : TNotifyEvent);
265287 procedure SetOnStateChanged (const Value : TLLMStateChangedEvent);
266288 procedure SetBusy (AValue: Boolean);
267289 procedure SetOnQARankingResult (const Value : TLLMQARankingResult);
268290 procedure SetOnTextEmbeddingResult (const Value : TLLMTextEmbeddingResult);
269291
270292 procedure ChatEnd (AState: Integer);
293+ procedure CallChatEnd (AState: Integer);
271294 procedure TextEmbeddingEnd (AState: Integer);
272295 procedure QARankingEnd (AState: Integer);
296+ procedure SetAIPrefix (const Value : string);
297+
298+ protected
299+ FThinking: Boolean;
300+ procedure InternalChunk (S: string);
301+ protected
302+ procedure DoBeforeChat ; virtual ;
303+ procedure HandlePrint (APrintType: Integer; S: string); virtual ;
304+ procedure HandleEnd ; virtual ;
273305 public
274306 constructor Create;
275307 destructor Destroy; override;
@@ -286,13 +318,18 @@ TChatLLM = class
286318 function ToolCompletion (const AInput: string): Integer;
287319 procedure AbortGeneration ;
288320
321+ function CallChat (const AInput: string; OnResult: TLLMPrintEvent): Integer;
322+
289323 function TextEmbedding (const AText: string): Integer;
290324 function QARanking (const AQustion, AAnswer: string): Integer;
325+ function RAGSelectStore (const AName: string): Integer;
291326
292327 property GenMaxTokens: Integer write SetGenMaxTokens;
293328 property Busy: Boolean read GetBusy;
294329 public
295330 property OnChunk: TLLMPrintEvent read FOnChunk write SetOnChunk;
331+ property OnThoughtChunk: TLLMPrintEvent read FOnThoughtChunk write FOnThoughtChunk;
332+ property OnThoughtEnded: TNotifyEvent read FOnThoughtEnded write FOnThoughtEnded;
296333 property OnPrintMeta: TLLMPrintEvent read FOnPrintMeta write SetOnPrintMeta;
297334 property OnPrintError: TLLMPrintEvent read FOnPrintError write SetOnPrintError;
298335 property OnPrintReference: TLLMPrintEvent read FOnPrintReference write SetOnPrintReference;
@@ -306,6 +343,15 @@ TChatLLM = class
306343 property OnQARankingResult: TLLMQARankingResult read FOnQARankingResult write SetOnQARankingResult;
307344
308345 property OnStateChanged: TLLMStateChangedEvent read FOnStateChanged write SetOnStateChanged;
346+
347+ property OutputAcc: string read FOutputAcc;
348+ property ThoughtAcc: string read FThoughtAcc;
349+ property ModelInfo: string read FModelInfo;
350+
351+ property AIPrefix: string write SetAIPrefix;
352+ property AutoAbortSufffix: string read FAutoAbortSufffix write FAutoAbortSufffix;
353+
354+ property References: TStringList read FReferences;
309355 end ;
310356
311357implementation
@@ -510,14 +556,14 @@ function _RunThreadedTask(Parameter : Pointer): IntPtr;
510556procedure TThreadedTask.Start (ANext: TLLMAPIEnded);
511557begin
512558 FNext := ANext;
513- { $ifdef fpc}
514- BeginThread(_RunThreadedTask, Self);
515- { $else}
559+ { $ifdef dcc}
516560 var T := TTask.Create(procedure
517561 begin
518562 _RunThreadedTask(Self);
519563 end );
520564 T.Start;
565+ { $else}
566+ BeginThread(_RunThreadedTask, Self);
521567{ $endif}
522568end ;
523569
@@ -561,6 +607,20 @@ procedure TChatLLM.AbortGeneration;
561607 ChatllmAbortGeneration(FObj);
562608end ;
563609
610+ function TChatLLM.CallChat (const AInput: string; OnResult: TLLMPrintEvent
611+ ): Integer;
612+ begin
613+ if Busy then Exit(-1 );
614+
615+ FReferences.Clear;
616+ Result := 0 ;
617+ SetBusy(True);
618+
619+ FCallingMode := True;
620+ FCallResult := OnResult;
621+ TThreadedChatTask.Create(Self, AInput).Start(CallChatEnd);
622+ end ;
623+
564624procedure TChatLLM.AddParam (AParams: array of string);
565625var
566626 S: string;
@@ -585,7 +645,11 @@ procedure TChatLLM.AddParam(AParams: TStrings);
585645function TChatLLM.Chat (const AInput: string): Integer;
586646begin
587647 if Busy then Exit(-1 );
588-
648+ DoBeforeChat;
649+ FReferences.Clear;
650+ FOutputAcc := ' ' ;
651+ FThinking := False;
652+ FThoughtAcc := ' ' ;
589653 Result := 0 ;
590654 SetBusy(True);
591655
@@ -595,11 +659,13 @@ function TChatLLM.Chat(const AInput: string): Integer;
595659constructor TChatLLM.Create;
596660begin
597661 inherited ;
662+ FReferences := TStringList.Create;
598663 FObj := ChatLLMCreate;
599664end ;
600665
601666destructor TChatLLM.Destroy;
602667begin
668+ FReferences.Free;
603669 inherited ;
604670end ;
605671
@@ -627,10 +693,12 @@ procedure TChatLLM.HandlePrint(APrintType: Integer; S: string);
627693 Ord(TPrintType.PRINTLN_ERROR):
628694 begin
629695 if Assigned(FOnPrintError) then
630- FOnPrintError(Self, S);
696+ FOnPrintError(Self, S)
697+ else ;
631698 end ;
632699 Ord(TPrintType.PRINTLN_REF):
633700 begin
701+ FReferences.Add(S);
634702 if Assigned(FOnPrintReference) then
635703 FOnPrintReference(Self, S);
636704 end ;
@@ -656,6 +724,21 @@ procedure TChatLLM.HandlePrint(APrintType: Integer; S: string);
656724 end ;
657725 Ord(TPrintType.PRINTLN_EMBEDDING), Ord(TPrintType.PRINTLN_RANKING):
658726 FMiscResult := S;
727+ Ord(TPrintType.PRINTLN_MODEL_INFO):
728+ FModelInfo := S;
729+ Ord(TPrintType.PRINT_THOUGHT_CHUNK):
730+ begin
731+ FThinking := True;
732+ FThoughtAcc := FThoughtAcc + S;
733+ if Assigned(FOnThoughtChunk) then
734+ FOnThoughtChunk(Self, S);
735+ end ;
736+ Ord(TPrintType.PRINT_EVT_THOUGHT_COMPLETED):
737+ begin
738+ FThinking := False;
739+ if Assigned(FOnThoughtEnded) then
740+ FOnThoughtEnded(Self);
741+ end ;
659742 end ;
660743end ;
661744
@@ -670,6 +753,11 @@ function TChatLLM.QARanking(const AQustion, AAnswer: string): Integer;
670753 TThreadedQATask.Create(Self, AQustion, AAnswer).Start(QARankingEnd);
671754end ;
672755
756+ function TChatLLM.RAGSelectStore (const AName: string): Integer;
757+ begin
758+ Result := ChatLLMRAGSelectStore(FObj, PAnsiChar(UTF8Encode(AName)));
759+ end ;
760+
673761procedure TChatLLM.Restart (ASysPrompt: string);
674762begin
675763 ChatLLMRestart(FObj, PAnsiChar(UTF8Encode(ASysPrompt)));
@@ -680,6 +768,21 @@ procedure TChatLLM.Restart;
680768 ChatLLMRestart(FObj, nil );
681769end ;
682770
771+ procedure TChatLLM.SetAIPrefix (const Value : string);
772+ begin
773+ ChatLLMSetAIPrefix(FObj, PAnsiChar(UTF8Encode(Value )));
774+ end ;
775+
776+ procedure TChatLLM.InternalChunk (S: string);
777+ begin
778+
779+ end ;
780+
781+ procedure TChatLLM.DoBeforeChat ;
782+ begin
783+
784+ end ;
785+
683786procedure TChatLLM.SetBusy (AValue: Boolean);
684787var
685788 F: Boolean;
@@ -775,20 +878,27 @@ procedure TChatLLM.ChatEnd(AState: Integer);
775878 SetBusy(False);
776879end ;
777880
881+ procedure TChatLLM.CallChatEnd (AState: Integer);
882+ begin
883+ FCallingMode := False;
884+ FCallResult(Self, FOutputAcc);
885+ SetBusy(False);
886+ end ;
887+
778888procedure TChatLLM.TextEmbeddingEnd (AState: Integer);
779889var
780- A: array of Single;
781- { $ifdef fpc}
782- L: array of string;
783- { $else}
890+ A: array of Single = nil ;
891+ { $ifdef dcc}
784892 L: TArray<string>;
893+ { $else}
894+ L: array of string;
785895{ $endif}
786896 I: Integer;
787897begin
788898 SetBusy(False);
789899 if not Assigned(FOnTextEmbeddingResult) then Exit;
790900
791- L := FMiscResult.Split([' ,' , ' ' ] );
901+ L := FMiscResult.Split([' ,' , ' ' , # 10 , # 13 ], TStringSplitOptions.ExcludeEmpty );
792902 SetLength(A, Length(L));
793903 for I := 0 to Length(L) - 1 do
794904 begin
0 commit comments