1
1
import json
2
- from promptflow .tracing import trace , start_trace
2
+ import logging
3
+ from promptflow .tracing import trace
3
4
from api .agents .researcher import researcher
4
5
from api .agents .writer import writer
5
6
from api .agents .editor import editor
6
7
from api .agents .designer import designer
7
8
from api .agents .product import product
9
+ from api .logging import log_output
10
+ from api .evaluate .evaluators import evaluate_article_in_background
11
+
8
12
from dotenv import load_dotenv
9
13
load_dotenv ()
10
14
11
15
@trace
12
- def get_research (context , instructions , feedback ):
13
-
16
+ def get_research (request , instructions , feedback ):
14
17
research_result = researcher .research (
15
- context = context ,
18
+ request = request ,
16
19
instructions = instructions ,
17
20
feedback = feedback
18
21
)
@@ -23,10 +26,9 @@ def get_research(context, instructions, feedback):
23
26
24
27
25
28
@trace
26
- def get_writer (context , feedback , instructions , research = [], products = []):
27
-
29
+ def get_writer (request , feedback , instructions , research = [], products = []):
28
30
writer_reponse = writer .write (
29
- context = context , feedback = feedback , instructions = instructions , research = research , products = products
31
+ request = request , feedback = feedback , instructions = instructions , research = research , products = products
30
32
)
31
33
print (json .dumps (writer_reponse , indent = 2 ))
32
34
return writer_reponse
@@ -41,12 +43,13 @@ def get_editor(article, feedback):
41
43
42
44
43
45
@trace
44
- def get_designer (context , instructions , feedback ):
45
- designer_task = designer .design (context , instructions , feedback )
46
+ def get_designer (request , instructions , feedback ):
47
+ designer_task = designer .design (request , instructions , feedback )
46
48
print (json .dumps (designer_task , indent = 2 ))
47
49
return designer_task
48
50
49
51
52
+ # TODO: delete, I dont think this is used...
50
53
@trace
51
54
def regenerate_process (editor_response , context , instructions , product_documenation ):
52
55
# Get feedback for research from writer
@@ -72,67 +75,78 @@ def regenerate_process(editor_response, context, instructions, product_documenat
72
75
)
73
76
return editor_response
74
77
75
-
76
78
@trace
77
- def get_article (context , instructions ):
78
- # This code is dup in api response to ueild steped results. TODO: Fix this so its not dup later
79
+ def write_article (request , instructions , evaluate = False ):
80
+ log_output ("Article generation started for request: %s, instructions: %s" , request , instructions )
81
+
82
+ feedback = "No Feedback"
83
+
84
+ # Researcher task look up the info
85
+ yield ("message" , "Starting research agent task..." )
86
+ log_output ("Getting researcher task output..." )
87
+ research_result = get_research (request , instructions , feedback )
88
+ yield ("researcher" , research_result )
89
+
90
+ # Retrieve product information relevant to the user's query
91
+ log_output ("Product information..." )
92
+ product_documenation = product .get_products (request )
93
+ yield ("products" , product_documenation )
94
+
95
+ # Then send it to the writer, the writer writes the article
96
+ yield ("message" , "Starting writer agent task..." )
97
+ log_output ("Getting writer task output..." )
98
+ writer_response = get_writer (request , feedback , instructions , research = research_result , products = product_documenation )
99
+ yield ("writer" , writer_response )
100
+
101
+ # Then send it to the editor, to decide if it's good or not
102
+ yield ("message" , "Starting editor agent task..." )
103
+ log_output ("Getting editor task output..." )
104
+ editor_response = get_editor (writer_response ["article" ], writer_response ["feedback" ])
105
+ log_output ("Editor response: %s" , editor_response )
106
+
107
+ yield ("editor" , editor_response )
108
+ retry_count = 0
109
+ while (str (editor_response ["decision" ]).lower ().startswith ("accept" )):
110
+ yield ("message" , f"Sending editor feedback ({ retry_count + 1 } )..." )
111
+ log_output ("Regeneration attempt %d based on editor feedback" , retry_count + 1 )
112
+
113
+ # Regenerate with feedback loop
114
+ researchFeedback = editor_response .get ("researchFeedback" , "No Feedback" )
115
+ editorFeedback = editor_response .get ("editorFeedback" , "No Feedback" )
116
+
117
+ research_result = get_research (request , instructions , researchFeedback )
118
+ yield ("researcher" , research_result )
119
+
120
+ writer_response = get_writer (request , editorFeedback , instructions , research = research_result , products = product_documenation )
121
+ yield ("writer" , writer_response )
122
+
123
+ editor_response = get_editor (writer_response ["article" ], writer_response ["feedback" ])
124
+ yield ("editor" , editor_response )
125
+
126
+ retry_count += 1
127
+ if retry_count >= 2 :
128
+ break
129
+
130
+ log_output ("Editor accepted article after %d iterations" , retry_count )
131
+ yield ("message" , "Editor accepted article" )
132
+
133
+ if evaluate :
134
+ evaluate_article_in_background (
135
+ request = request ,
136
+ instructions = instructions ,
137
+ research = research_result ,
138
+ products = product_documenation ,
139
+ article = writer_response
140
+ )
141
+
142
+ # Log final editor response
143
+ log_output ("Final editor response: %s" , json .dumps (editor_response , indent = 2 ))
79
144
80
- feedback = ""
81
- print ("Getting article for context: " , context )
82
-
83
- # researcher task look up the info
84
- print ("Getting researcher task output..." )
85
- research_result = get_research (context , instructions , feedback )
86
- product_documenation = product .get_products (context )
87
-
88
- # then send it to the writer, the writer writes the article
89
- print ("Getting writer task output..." )
90
- writer_reponse = get_writer (
91
- context , feedback , instructions , research = research_result , products = product_documenation
92
- )
93
-
94
- # then send it to the editor, to decide if it's good or not
95
- print ("Getting editor task output..." )
96
- editor_response = get_editor (
97
- writer_reponse ["article" ], writer_reponse ["feedback" ]
98
- )
99
- print (editor_response )
100
-
101
- # retry until decision is accept or until 2x tries
102
- if editor_response ["decision" ] == "reject" :
103
- print ("Editor rejected writer, sending back to writer (1)..." )
104
- # retry research, writer, and editor with feedback from writer and editor
105
- editor_response = regenerate_process (editor_response , context , instructions , product_documenation )
106
-
107
- if editor_response ["decision" ] == "reject" :
108
- print ("Editor rejected writer again, sending back to writer (2)..." )
109
- # retry research, writer, and editor with feedback from writer and editor
110
- editor_response = regenerate_process (editor_response , context , product_documenation )
111
-
112
- print ("Editor accepted writer and research, sending to designer..." )
113
- # SETH TODO: send to designer
114
- # designer_task = designer.design(context, instructions, feedback)
115
- # create result object with editor response and writer response
116
- result = {"editor_response" : editor_response , "writer_response" : writer_reponse }
117
- print (json .dumps (result , indent = 2 ))
118
- return result
119
-
120
145
if __name__ == "__main__" :
121
- import os
122
- from opentelemetry import trace
123
- from opentelemetry .sdk .trace import TracerProvider
124
- from opentelemetry .sdk .trace .export import BatchSpanProcessor
125
- from azure .monitor .opentelemetry .exporter import AzureMonitorTraceExporter
126
-
127
- # log to app insights if configured
128
- if 'APPINSIGHTS_CONNECTION_STRING' in os .environ :
129
- connection_string = os .environ ['APPINSIGHTS_CONNECTION_STRING' ]
130
- trace .set_tracer_provider (TracerProvider ())
131
- trace .get_tracer_provider ().add_span_processor (BatchSpanProcessor (AzureMonitorTraceExporter (connection_string = connection_string )))
132
-
133
- # start pf tracing
134
- start_trace ()
146
+ from api .logging import init_logging
135
147
148
+ init_logging ()
136
149
context = "Can you find the latest camping trends and what folks are doing in the winter?"
137
150
instructions = "Can you find the relevant information needed and good places to visit"
138
- get_article (context , instructions )
151
+ for result in write_article (context , instructions , evaluate = True ):
152
+ print (* result )
0 commit comments