@@ -3,11 +3,13 @@ import Logger
33import OpenAIService
44
55public class FunctionCallingChatAgent < Output: AgentOutputParsable & Decodable > : Agent {
6+ public typealias ScratchPadContent = [ ChatMessage ]
7+
68 public struct EndFunction : ChatGPTFunction {
79 public typealias Argument = Output
810 public typealias Result = String
9- public var name : String { " sendFinalAnswer " }
10- public var description : String { " Send the final answer to user " }
11+ public var name : String { " saveFinalAnswer " }
12+ public var description : String { " Save the final answer when it's ready " }
1113 public let argumentSchema : JSONSchemaValue
1214 public var reportProgress : ( String ) async -> Void = { _ in }
1315 public func prepare( ) async { }
@@ -71,16 +73,16 @@ public class FunctionCallingChatAgent<Output: AgentOutputParsable & Decodable>:
7173 public typealias Input = String
7274 public var observationPrefix : String { " Observation: " }
7375 public var llmPrefix : String { " Thought: " }
74- public let chatModelChain : ChatModelChain < AgentInput < String > >
76+ public let chatModelChain : ChatModelChain < AgentInput < String , ScratchPadContent > >
7577 var functionProvider : FunctionProvider
7678
7779 public init (
7880 configuration: ChatGPTConfiguration = UserPreferenceChatGPTConfiguration ( ) ,
7981 tools: [ AgentTool ] = [ ] ,
8082 endFunction: EndFunction
8183 ) {
82- let functions = tools. compactMap { $0 as? FunctionCallingAgentTool } . map ( \ . function )
83- let otherTools = tools. filter { !( $0 is FunctionCallingAgentTool ) }
84+ let functions = tools. compactMap { $0 as? ( any ChatGPTFunction ) }
85+ let otherTools = tools. filter { !( $0 is ( any ChatGPTFunction ) ) }
8486 functionProvider = . init(
8587 tools: otherTools,
8688 functionTools: functions,
@@ -102,38 +104,18 @@ public class FunctionCallingChatAgent<Output: AgentOutputParsable & Decodable>:
102104 role: . system,
103105 content: """
104106 Respond to the human as helpfully and accurately as possible. \
105- Format final answer to be more readable, in a ordered list if possible. \
107+ Save the final answer when it's ready
106108
107109 Begin!
108110 """
109111 ) ,
110- agentInput. thoughts. isEmpty
111- ? . init( role: . user, content: agentInput. input)
112- : . init(
113- role: . user,
114- content: """
115- \( agentInput. input)
116-
117- \( {
118- switch agentInput. thoughts {
119- case let . text( text) :
120- return text
121- case let . messages( messages) :
122- return messages. map { message in
123- """
124- \( message)
125- """
126- } . joined ( separator: " \n " )
127- }
128- } ( ) )
129- """
130- ) ,
131- ]
112+ . init( role: . user, content: agentInput. input)
113+ ] + agentInput. thoughts. content
132114 }
133115 )
134116 }
135117
136- public func extraPlan( input: AgentInput < String > ) {
118+ public func extraPlan( input: AgentInput < String , ScratchPadContent > ) {
137119 // no extra plan
138120 }
139121
@@ -142,14 +124,34 @@ public class FunctionCallingChatAgent<Output: AgentOutputParsable & Decodable>:
142124 return " (call sendFinalAnswer to finish) "
143125 }
144126
145- public func constructScratchpad( intermediateSteps: [ AgentAction ] ) -> AgentScratchPad {
146- let baseScratchpad = constructBaseScratchpad ( intermediateSteps: intermediateSteps)
147- if baseScratchpad. isEmpty { return . text( " " ) }
148- return . text( """
149- This was your previous work (but I haven't seen any of it! I only see what you return as `Final Answer`):
150- \( baseScratchpad)
151- (Please continue with `Thought:` or call a function)
152- """ )
127+ public func constructScratchpad(
128+ intermediateSteps: [ AgentAction ]
129+ ) -> AgentScratchPad < ScratchPadContent > {
130+ let baseScratchpad = intermediateSteps. flatMap {
131+ [
132+ ChatMessage (
133+ role: . assistant,
134+ content: nil ,
135+ functionCall: . init( name: $0. toolName, arguments: $0. toolInput)
136+ ) ,
137+ ChatMessage ( role: . function, content: $0. observation) ,
138+ ]
139+ }
140+ return . init( content: baseScratchpad)
141+ }
142+
143+ public func constructFinalScratchpad( intermediateSteps: [ AgentAction ] ) -> AgentScratchPad < ScratchPadContent > {
144+ let baseScratchpad = intermediateSteps. flatMap {
145+ [
146+ ChatMessage (
147+ role: . assistant,
148+ content: nil ,
149+ functionCall: . init( name: $0. toolName, arguments: $0. toolInput)
150+ ) ,
151+ ChatMessage ( role: . function, content: $0. observation) ,
152+ ]
153+ }
154+ return . init( content: baseScratchpad)
153155 }
154156
155157 public func validateTools( tools: [ AgentTool ] ) throws {
@@ -185,7 +187,7 @@ public class FunctionCallingChatAgent<Output: AgentOutputParsable & Decodable>:
185187 }
186188 }
187189 }
188-
190+
189191 // fallback to normal agent.
190192
191193 let stringBaseOutput = await ChatAgent (
0 commit comments