kevinhug commited on
Commit
4664994
·
1 Parent(s): fa93fef

human-in-the-loop

Browse files
Files changed (2) hide show
  1. app.py +41 -0
  2. human.py +166 -0
app.py CHANGED
@@ -6,6 +6,7 @@ from knowledge import graph
6
  from pii import derisk
7
  from classify import judge
8
  from entity import resolve
 
9
 
10
  # Define the Google Analytics script
11
  head = """
@@ -478,4 +479,44 @@ For example, Comcast reduced repeat service calls by 17% after deploying entity
478
 
479
  The result? Less agent time lost, higher customer satisfaction, and data pipelines that actually speak human.
480
  """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  demo.launch(allowed_paths=["."])
 
6
  from pii import derisk
7
  from classify import judge
8
  from entity import resolve
9
+ from human import email, feedback
10
 
11
  # Define the Google Analytics script
12
  head = """
 
479
 
480
  The result? Less agent time lost, higher customer satisfaction, and data pipelines that actually speak human.
481
  """)
482
+ with gr.Tab("Human Feedback Content"):
483
+ gr.Markdown("""
484
+ Objective: Leveraging Human Feedback to Deliver Personalized Content that Proactively Solves Customer Pain Points
485
+ ================================================
486
+ """)
487
+
488
+ in_verbatim = gr.Textbox(label="Persona")
489
+ in_campaign = gr.Textbox(label="campaign")
490
+ out_product = gr.Textbox(label="Your Personalized Email Campaign Bot")
491
+
492
+ gr.Examples(
493
+ [
494
+ ["""My mortgage rate is 9%, I cannot afford it anymore, I need to refinance and I'm unemploy right now.""", "MORT"],
495
+ ["my credit card limit is too low, I need a card with bigger limit and low fee", "CARD"]
496
+ ],
497
+ [in_verbatim, in_campaign]
498
+ )
499
+ btn_recommend = gr.Button("Resolve")
500
+ btn_recommend.click(fn=email, inputs=[in_verbatim, in_campaign, out_product], outputs=out_product)
501
+
502
+ h_feedback = gr.Radio(['approved', 'rejected'], label="Human Feedback", info="Which campaign you want to approve?")
503
+ h_campaign = gr.Textbox(label="campaign")
504
+ btn_deliver = gr.Button("Deliver?")
505
+ btn_deliver.click(fn=feedback, inputs=[h_feedback, h_campaign, out_product], outputs=out_product)
506
+
507
+ gr.Markdown("""
508
+ Human Feedback for Personalized Content enables brands like Mr. Cooper to analyze customer preferences and pain points, then deliver tailored solutions. By embedding real-time feedback loops, they created personalized mortgage-refinancing videos showcasing individual home equity data and financial goals, resulting in 18% higher engagement and 12% lower churn.
509
+
510
+ #### Outcome:
511
+
512
+ - Dynamic content adaptation based on behavioral data (e.g., Hilton Honors’ app reduced booking friction by 40% via predictive analytics)
513
+
514
+ - Proactive problem-solving (e.g., Orangetheory Fitness used workout metrics to boost class attendance to 97%)
515
+
516
+ - 52% faster ROI through AI-driven personalization scaling
517
+
518
+ #### Ask: Ready to turn customer frustrations into loyalty drivers with content that feels personally crafted?"
519
+
520
+ This approach aligns with best-in-class use cases where feedback-driven personalization drives measurable business growth
521
+ """)
522
  demo.launch(allowed_paths=["."])
human.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Annotated, Any, Literal
2
+
3
+ from langchain_community.tools.tavily_search import TavilySearchResults
4
+ from langchain_core.prompts import ChatPromptTemplate
5
+ from langchain_core.tools import tool
6
+ from langgraph.checkpoint.memory import MemorySaver
7
+ from langgraph.graph import StateGraph, START, END
8
+ from langgraph.graph.message import add_messages
9
+ from langgraph.types import interrupt, Command
10
+ from typing_extensions import TypedDict
11
+
12
+ """
13
+ from langchain_anthropic import ChatAnthropic
14
+ from langchain_ollama.llms import OllamaLLM
15
+ from langchain_experimental.llms.ollama_functions import OllamaFunctions
16
+ llm = OllamaFunctions(model="qwen2.5", format="json")
17
+ llm_with_tools = llm #.bind_tools(tools)
18
+ """
19
+
20
+ from langchain_groq import ChatGroq
21
+
22
+ llm = ChatGroq(
23
+ model="llama-3.1-8b-instant",
24
+ temperature=0,
25
+ max_tokens=None,
26
+ timeout=None,
27
+ max_retries=2,
28
+ # other params...
29
+ )
30
+
31
+ template = """Question: {question}
32
+ Answer: Let's think step by step."""
33
+
34
+ prompt = ChatPromptTemplate.from_template(template)
35
+
36
+ # model = OllamaLLM(model="deepseek-r1")
37
+
38
+ chain = prompt | llm
39
+
40
+
41
+ # print(chain.invoke({"question": "Explain like I'm 5 for capacity planning?"}))
42
+
43
+ @tool
44
+ def human_assistance(query: str) -> str:
45
+ """Request assistance from a human."""
46
+ human_response = interrupt({"query": query})
47
+ return human_response["data"]
48
+
49
+
50
+ tool = TavilySearchResults(max_results=2)
51
+ tools = [tool, human_assistance]
52
+ llm_with_tools=llm.bind_tools(tools)
53
+
54
+ # llm = OllamaLLM(model="deepseek-r1") #ChatAnthropic(model="claude-3-5-sonnet-20240620")
55
+
56
+ class State(TypedDict):
57
+ messages: Annotated[list, add_messages]
58
+ persona: str
59
+ email: str
60
+ release: Literal['approve', 'reject']
61
+
62
+
63
+ graph_builder = StateGraph(State)
64
+
65
+
66
+ def write_email(state: State):
67
+ prompt = f"""Write an promotional personalized email for this persona:
68
+ {state["persona"]}
69
+ """
70
+ email = llm_with_tools.invoke(prompt)
71
+ # Because we will be interrupting during tool execution,
72
+ # we disable parallel tool calling to avoid repeating any
73
+ # tool invocations when we resume.
74
+ # assert len(email.tool_calls) <= 1
75
+ return Command(update={"email": email.content})
76
+
77
+
78
+ graph_builder.add_node("write_email", write_email)
79
+
80
+
81
+ def delivery(state: State):
82
+ print(f"""Delivering: {state['email']}""")
83
+
84
+ return Command(update={"messages": ["Email delivered to customer"]})
85
+
86
+
87
+ graph_builder.add_node("delivery", delivery)
88
+
89
+
90
+ def human_approval(state: State) -> Command[Literal["delivery", END]]:
91
+ is_approved = interrupt(
92
+ "Approval for release the promotional email to customer? (type: approved or rejected):"
93
+ )
94
+
95
+ if is_approved == "approved":
96
+ return Command(goto="delivery", update={"release": "approved"})
97
+ else:
98
+ return Command(goto=END, update={"release": "rejected"})
99
+
100
+
101
+ # Add the node to the graph in an appropriate location
102
+ # and connect it to the relevant nodes.
103
+ graph_builder.add_node("human_approval", human_approval)
104
+
105
+ graph_builder.add_edge(START, "write_email")
106
+ graph_builder.add_edge("write_email", "human_approval")
107
+
108
+ graph_builder.add_edge("delivery", END)
109
+
110
+ checkpointer = MemorySaver()
111
+ graph = graph_builder.compile(checkpointer=checkpointer)
112
+
113
+
114
+ def email(persona, campaign, history):
115
+ thread_config = {"configurable": {"thread_id": campaign}}
116
+ for event in graph.stream({"persona": persona}, config=thread_config):
117
+ for value in event.values():
118
+ return r"\nAssistant: ", value, r"\nValue: ", graph.get_state(thread_config).values
119
+
120
+
121
+ def feedback(deliver, campaign, history):
122
+ thread_config = {"configurable": {"thread_id": campaign}}
123
+ for event in graph.stream(Command(resume=deliver), config=thread_config):
124
+ for value in event.values():
125
+ return r"\nAssistant: ", value, r"\nValue: ", graph.get_state(thread_config).values
126
+
127
+
128
+ '''
129
+ from IPython.display import Image, display
130
+
131
+ try:
132
+ display(Image(graph.get_graph().draw_mermaid_png()))
133
+ except Exception:
134
+ # This requires some extra dependencies and is optional
135
+ pass
136
+ '''
137
+
138
+ def campaign(user_input: Any, id: str):
139
+ thread_config = {"configurable": {"thread_id": id}}
140
+ for event in graph.stream(user_input, config=thread_config):
141
+ for value in event.values():
142
+ print("Assistant:", value, "Value: ", graph.get_state(thread_config).values)
143
+
144
+ """
145
+ campaign({"persona": "My mortgage rate is 9%, I cannot afford it anymore, I need to refinance and I'm unemploy right now."}, "MOR")
146
+
147
+ campaign({"persona": "my credit card limit is too low, I need a card with bigger limit and low fee"}, "CARD")
148
+
149
+ campaign(Command(resume="approved"), "MOR")
150
+ """
151
+
152
+ while False:
153
+ try:
154
+ user_input = input("User: ")
155
+ if user_input.lower() in ["quit", "exit", "q"]:
156
+ print("Goodbye!")
157
+ break
158
+ campaign(user_input, "MORT")
159
+ # stream_graph_updates(user_input)
160
+ except Exception as e:
161
+ # fallback if input() is not available
162
+ user_input = "What do you know about LangGraph?"
163
+ print("User: " + user_input)
164
+ campaign(user_input, "MORT")
165
+ # stream_graph_updates(user_input)
166
+ break