-
-
Notifications
You must be signed in to change notification settings - Fork 427
Expand file tree
/
Copy pathAgent.swift
More file actions
177 lines (146 loc) · 5.38 KB
/
Agent.swift
File metadata and controls
177 lines (146 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import Foundation
public struct AgentAction: Equatable {
public var toolName: String
public var toolInput: String
public var log: String
public var observation: String?
public init(toolName: String, toolInput: String, log: String, observation: String? = nil) {
self.toolName = toolName
self.toolInput = toolInput
self.log = log
self.observation = observation
}
public func observationAvailable(_ observation: String) -> AgentAction {
var newAction = self
newAction.observation = observation
return newAction
}
}
public extension CallbackEvents {
struct AgentDidFinish<Output: AgentOutputParsable>: CallbackEvent {
public let info: AgentFinish<Output>
}
static func agentDidFinish<Output: AgentOutputParsable>() -> AgentDidFinish<Output>.Type {
AgentDidFinish<Output>.self
}
struct AgentActionDidStart: CallbackEvent {
public let info: AgentAction
}
var agentActionDidStart: AgentActionDidStart.Type {
AgentActionDidStart.self
}
struct AgentActionDidEnd: CallbackEvent {
public let info: AgentAction
}
var agentActionDidEnd: AgentActionDidEnd.Type {
AgentActionDidEnd.self
}
struct AgentFunctionCallingToolReportProgress: CallbackEvent {
public struct Info {
public let functionName: String
public let progress: String
}
public let info: Info
}
var agentFunctionCallingToolReportProgress: AgentFunctionCallingToolReportProgress.Type {
AgentFunctionCallingToolReportProgress.self
}
}
public struct AgentFinish<Output: AgentOutputParsable> {
public enum ReturnValue {
case structured(Output)
case unstructured(String)
}
public var returnValue: ReturnValue
public var log: String
public init(returnValue: ReturnValue, log: String) {
self.returnValue = returnValue
self.log = log
}
}
extension AgentFinish.ReturnValue: Equatable where Output: Equatable {}
extension AgentFinish: Equatable where Output: Equatable {}
public enum AgentNextStep<Output: AgentOutputParsable> {
case actions([AgentAction])
case finish(AgentFinish<Output>)
}
extension AgentNextStep: Equatable where Output: Equatable {}
public struct AgentScratchPad<Content: Equatable>: Equatable {
public var content: Content
public init(content: Content) {
self.content = content
}
}
public struct AgentInput<T, ScratchPadContent: Equatable> {
public var input: T
public var thoughts: AgentScratchPad<ScratchPadContent>
public init(input: T, thoughts: AgentScratchPad<ScratchPadContent>) {
self.input = input
self.thoughts = thoughts
}
}
extension AgentInput: Equatable where T: Equatable {}
public enum AgentEarlyStopHandleType: Equatable {
case force
case generate
}
public protocol Agent {
associatedtype Input
associatedtype Output: AgentOutputParsable
associatedtype ScratchPadContent: Equatable
var chatModelChain: ChatModelChain<AgentInput<Input, ScratchPadContent>> { get }
func validateTools(tools: [AgentTool]) throws
func constructScratchpad(intermediateSteps: [AgentAction]) -> AgentScratchPad<ScratchPadContent>
func constructFinalScratchpad(intermediateSteps: [AgentAction])
-> AgentScratchPad<ScratchPadContent>
func extraPlan(input: AgentInput<Input, ScratchPadContent>)
func parseOutput(_ output: ChatModelChain<AgentInput<Input, ScratchPadContent>>.Output) async
-> AgentNextStep<Output>
}
public extension Agent {
func getFullInputs(
input: Input,
intermediateSteps: [AgentAction]
) -> AgentInput<Input, ScratchPadContent> {
let thoughts = constructScratchpad(intermediateSteps: intermediateSteps)
return AgentInput(input: input, thoughts: thoughts)
}
func plan(
input: Input,
intermediateSteps: [AgentAction],
callbackManagers: [CallbackManager]
) async throws -> AgentNextStep<Output> {
let input = getFullInputs(input: input, intermediateSteps: intermediateSteps)
extraPlan(input: input)
let output = try await chatModelChain.call(input, callbackManagers: callbackManagers)
return await parseOutput(output)
}
func returnStoppedResponse(
input: Input,
earlyStoppedHandleType: AgentEarlyStopHandleType,
intermediateSteps: [AgentAction],
callbackManagers: [CallbackManager]
) async throws -> AgentFinish<Output> {
switch earlyStoppedHandleType {
case .force:
return AgentFinish(
returnValue: .unstructured("Agent stopped due to iteration limit or time limit."),
log: ""
)
case .generate:
let thoughts = constructFinalScratchpad(intermediateSteps: intermediateSteps)
let input = AgentInput(input: input, thoughts: thoughts)
let output = try await chatModelChain.call(input, callbackManagers: callbackManagers)
let nextAction = await parseOutput(output)
switch nextAction {
case let .finish(finish):
return finish
case .actions:
return .init(
returnValue: .unstructured(output.content ?? ""),
log: output.content ?? ""
)
}
}
}
}