ABAO77 commited on
Commit
b4c9cb7
·
verified ·
1 Parent(s): 8f45596

Upload 67 files

Browse files
Files changed (29) hide show
  1. src/agents/agent_transcript/__pycache__/func.cpython-311.pyc +0 -0
  2. src/agents/agent_transcript/__pycache__/prompt.cpython-311.pyc +0 -0
  3. src/agents/agent_transcript/func.py +41 -5
  4. src/agents/agent_transcript/prompt.py +206 -121
  5. src/apis/__pycache__/create_app.cpython-311.pyc +0 -0
  6. src/apis/controllers/__pycache__/auth_controller.cpython-311.pyc +0 -0
  7. src/apis/controllers/auth_controller.py +36 -0
  8. src/apis/create_app.py +4 -2
  9. src/apis/interfaces/__pycache__/auth_interface.cpython-311.pyc +0 -0
  10. src/apis/interfaces/auth_interface.py +18 -0
  11. src/apis/middlewares/__pycache__/auth_middleware.cpython-311.pyc +0 -0
  12. src/apis/middlewares/auth_middleware.py +0 -2
  13. src/apis/models/__pycache__/BaseDocument.cpython-311.pyc +0 -0
  14. src/apis/models/__pycache__/prompt_models.cpython-311.pyc +0 -0
  15. src/apis/models/__pycache__/user_models.cpython-311.pyc +0 -0
  16. src/apis/models/prompt_models.py +14 -0
  17. src/apis/models/user_models.py +29 -0
  18. src/apis/providers/__pycache__/jwt_provider.cpython-311.pyc +0 -0
  19. src/apis/providers/jwt_provider.py +37 -0
  20. src/apis/routers/__pycache__/auth_router.cpython-311.pyc +0 -0
  21. src/apis/routers/__pycache__/gen_script.cpython-311.pyc +0 -0
  22. src/apis/routers/__pycache__/prompt_editor.cpython-311.pyc +0 -0
  23. src/apis/routers/auth_router.py +45 -0
  24. src/apis/routers/gen_script.py +47 -38
  25. src/apis/routers/prompt_editor.py +55 -0
  26. src/config/__pycache__/mongo.cpython-311.pyc +0 -0
  27. src/config/mongo.py +5 -13
  28. src/utils/__pycache__/helper.cpython-311.pyc +0 -0
  29. src/utils/helper.py +1 -0
src/agents/agent_transcript/__pycache__/func.cpython-311.pyc CHANGED
Binary files a/src/agents/agent_transcript/__pycache__/func.cpython-311.pyc and b/src/agents/agent_transcript/__pycache__/func.cpython-311.pyc differ
 
src/agents/agent_transcript/__pycache__/prompt.cpython-311.pyc CHANGED
Binary files a/src/agents/agent_transcript/__pycache__/prompt.cpython-311.pyc and b/src/agents/agent_transcript/__pycache__/prompt.cpython-311.pyc differ
 
src/agents/agent_transcript/func.py CHANGED
@@ -9,9 +9,16 @@ from src.utils.logger import logger
9
  from src.utils.helper import extract_transcript, extract_comment
10
  from .prompt import *
11
  import operator
 
 
12
 
13
 
14
  class State(TypedDict):
 
 
 
 
 
15
  video_link: str
16
  messages: Annotated[Sequence[AnyMessage], add_messages]
17
  transcript: str
@@ -43,10 +50,12 @@ def trim_history(state: State):
43
  return {}
44
 
45
 
46
- def extract_transcript_and_comment(state: State):
47
  transcript = extract_transcript(state["video_link"])
48
  comment = extract_comment(state["video_link"])
49
 
 
 
50
  # Calculate script count based on target word count
51
  # Assume each script is around 200-300 words
52
  avg_words_per_script = 1000
@@ -59,12 +68,25 @@ def extract_transcript_and_comment(state: State):
59
  "messages": HumanMessage(
60
  content=f"Will generate {script_count} scripts for {state.get('target_word_count', 8000)} words target"
61
  ),
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
 
64
 
65
  def script_structure_analyzer(state: State):
66
  transcript = state["transcript"]
67
- response = chain_script_structure_analyzer.invoke({"script": transcript})
 
 
68
  return {
69
  "script_structure_analyzer_response": response.content,
70
  "messages": HumanMessage(
@@ -80,6 +102,7 @@ def comment_insight_extractor(state: State):
80
  "script_structure_analyzer_response": state[
81
  "script_structure_analyzer_response"
82
  ],
 
83
  }
84
  )
85
  return {
@@ -102,7 +125,10 @@ Comment Insight Extractor Response: {state["comment_insight_extractor_response"]
102
  """,
103
  }
104
  ]
105
- response = scientific_fact_agent.invoke(input_message)
 
 
 
106
  research_insight = response["messages"][-1].content
107
  return {
108
  "research_insight_response": research_insight,
@@ -113,7 +139,12 @@ Comment Insight Extractor Response: {state["comment_insight_extractor_response"]
113
 
114
 
115
  def script_re_outline(state: State):
116
- response = chain_script_re_outline.invoke({"messages": state["messages"]})
 
 
 
 
 
117
  return {
118
  "script_re_outline_response": response.content,
119
  "messages": HumanMessage(
@@ -154,7 +185,12 @@ def script_writer_single(state: State):
154
  current_messages.append(HumanMessage(content=word_prompt))
155
 
156
  # Generate script
157
- response = chain_script_writer.invoke({"messages": current_messages})
 
 
 
 
 
158
  script_out.append(response.content)
159
 
160
  # Add response to message history
 
9
  from src.utils.helper import extract_transcript, extract_comment
10
  from .prompt import *
11
  import operator
12
+ from src.config.mongo import PromptCRUD
13
+ from pydantic import BaseModel, Field
14
 
15
 
16
  class State(TypedDict):
17
+ script_structure_analyzer_prompt: str
18
+ comment_insight_extractor_prompt: str
19
+ scientific_fact_finder_prompt: str
20
+ script_re_outline_prompt: str
21
+ script_writer_prompt: str
22
  video_link: str
23
  messages: Annotated[Sequence[AnyMessage], add_messages]
24
  transcript: str
 
50
  return {}
51
 
52
 
53
+ async def extract_transcript_and_comment(state: State):
54
  transcript = extract_transcript(state["video_link"])
55
  comment = extract_comment(state["video_link"])
56
 
57
+ prompt_template = await PromptCRUD.read({})
58
+ prompt_template = prompt_template[0]
59
  # Calculate script count based on target word count
60
  # Assume each script is around 200-300 words
61
  avg_words_per_script = 1000
 
68
  "messages": HumanMessage(
69
  content=f"Will generate {script_count} scripts for {state.get('target_word_count', 8000)} words target"
70
  ),
71
+ "script_structure_analyzer_prompt": prompt_template[
72
+ "script_structure_analyzer_prompt"
73
+ ],
74
+ "comment_insight_extractor_prompt": prompt_template[
75
+ "comment_insight_extractor_prompt"
76
+ ],
77
+ "scientific_fact_finder_prompt": prompt_template[
78
+ "scientific_fact_finder_prompt"
79
+ ],
80
+ "script_re_outline_prompt": prompt_template["script_re_outline_prompt"],
81
+ "script_writer_prompt": prompt_template["script_writer_prompt"],
82
  }
83
 
84
 
85
  def script_structure_analyzer(state: State):
86
  transcript = state["transcript"]
87
+ response = chain_script_structure_analyzer.invoke(
88
+ {"script": transcript, "prompt": state["script_structure_analyzer_prompt"]}
89
+ )
90
  return {
91
  "script_structure_analyzer_response": response.content,
92
  "messages": HumanMessage(
 
102
  "script_structure_analyzer_response": state[
103
  "script_structure_analyzer_response"
104
  ],
105
+ "prompt": state["comment_insight_extractor_prompt"],
106
  }
107
  )
108
  return {
 
125
  """,
126
  }
127
  ]
128
+ input_message["prompt"] = state["scientific_fact_finder_prompt"]
129
+ response = scientific_fact_finder_agent(
130
+ state["scientific_fact_finder_prompt"]
131
+ ).invoke(input_message)
132
  research_insight = response["messages"][-1].content
133
  return {
134
  "research_insight_response": research_insight,
 
139
 
140
 
141
  def script_re_outline(state: State):
142
+ response = chain_script_re_outline.invoke(
143
+ {
144
+ "messages": state["messages"],
145
+ "prompt": state["script_re_outline_prompt"],
146
+ }
147
+ )
148
  return {
149
  "script_re_outline_response": response.content,
150
  "messages": HumanMessage(
 
185
  current_messages.append(HumanMessage(content=word_prompt))
186
 
187
  # Generate script
188
+ response = chain_script_writer.invoke(
189
+ {
190
+ "messages": current_messages,
191
+ "prompt": state["script_writer_prompt"],
192
+ }
193
+ )
194
  script_out.append(response.content)
195
 
196
  # Add response to message history
src/agents/agent_transcript/prompt.py CHANGED
@@ -1,3 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from langchain_core.prompts import ChatPromptTemplate
2
  from src.config.llm import llm_2_0 as llm, llm_2_5_flash_preview
3
  from pydantic import BaseModel, Field
@@ -10,30 +194,7 @@ script_structure_analyzer_prompt = ChatPromptTemplate.from_messages(
10
  [
11
  (
12
  "system",
13
- """
14
- Vai trò: Bạn là Script Structure Analyzer trong một workflow của một nhóm các agent.
15
- Instruction:
16
- - Tự động phân tích kịch bản gốc, tách các phần (Mở bài, Thân bài, Điểm chốt, CTA)
17
- - Xác định công thức cấu trúc (AIDA, PAS, BFB,...)
18
- - Trích xuất hook, câu chuyển đoạn, CTA
19
- - Phát hiện điểm mạnh/yếu/chỗ lạc nhịp
20
-
21
- Input: Script gốc
22
- Output:
23
- - Outline:
24
- - Mở bài
25
- - Thân bài
26
- - Điểm chốt
27
- - CTA
28
- - Công thức cấu trúc
29
- - AIDA: Attention, Interest, Desire, Action
30
- - PAS: Problem, Agitation, Solution
31
- - BFB: Belief, Feeling, Behavior
32
- - Hook
33
- - Câu chuyển đoạn
34
- - CTA
35
- - Điểm mạnh/yếu/chỗ lạc nhịp
36
- """,
37
  ),
38
  ("user", "input script: {script}"),
39
  ]
@@ -43,28 +204,7 @@ comment_insight_extractor_prompt = ChatPromptTemplate.from_messages(
43
  [
44
  (
45
  "system",
46
- """
47
- Vai trò: Bạn là Comment Insight Extractor trong một workflow của một nhóm các agent phân tích youtube video.
48
- Instruction:
49
- - Đọc, phân tích tất cả comment, trích xuất insight
50
- - lọc ra các câu hỏi lặp lại, nỗi sợ/mong muốn/lợi ích/ngôn ngữ quen thuộc
51
- - So sánh insight với script gốc và xác định thiếu sót.
52
-
53
- Input:
54
- - Output từ Script Structure Analyzer Agent Youtube Video
55
- - Comment
56
-
57
- Output:
58
- - Insights Table:
59
- - Insight
60
- - Original Comment
61
- - Pain or Benefit
62
- - Suggest for Script
63
- - Missing From Script
64
- - Repeated Questions
65
- - Audience Language
66
-
67
- """,
68
  ),
69
  ("user", "input comment: {comment}"),
70
  (
@@ -77,22 +217,7 @@ scientific_fact_finder_prompt = ChatPromptTemplate.from_messages(
77
  [
78
  (
79
  "system",
80
- """
81
- Vai trò: Bạn là Scientific Fact Finder trong một workflow của một nhóm các agent phân tích youtube video.
82
- Instruction:
83
- - Tự động research 3-5 nghiên cứu khoa học thực tế (PubMed, JAMA, Circulation, Nutrients…), tóm tắt số liệu, trích nguồn, gợi ý số liệu phù hợp cho từng đoạn trong script mới.
84
- - So sánh fact science với script gốc và xác định thiếu sót.
85
-
86
- Input:
87
- - Output từ Script Structure Analyzer Agent Youtube Video
88
- - Output từ Comment Insight Extractor Agent Youtube Video
89
-
90
- Output List:
91
- - Title: Tên nghiên cứu
92
- - Summary: Tóm tắt nghiên cứu
93
- - Source: Nguồn nghiên cứu
94
- - Relevant for Section: Relevant cho section nào trong script mới
95
- """,
96
  ),
97
  ("placeholder", "{messages}"),
98
  ]
@@ -102,28 +227,7 @@ script_re_outline_prompt = ChatPromptTemplate.from_messages(
102
  [
103
  (
104
  "system",
105
- """
106
- Vai trò: Bạn là Script Re-Outline Agent trong một workflow của một nhóm các agent.
107
- Instruction:
108
- Kết hợp outline cũ, insight từ comment, fact từ research để lập outline mới: Hook mới, thứ tự section mới, CTA mới, các ý chuyển mạch rõ ràng, phân bổ fact/nghiên cứu vào các section.
109
-
110
- Input:
111
- - Output từ Script Structure Analyzer Agent
112
- - Output từ Comment Insight Extractor Agent
113
- - Output từ Scientific Fact Finder Agent
114
-
115
- Output:
116
-
117
- - Outline mới: (Section, summary, suggested length, facts to include)
118
- - Hook mở bài
119
- - Thân bài 1
120
- - Thân bài 2
121
- - Điểm chốt
122
- - CTA
123
- - CTA position
124
- - Transitions
125
- - Order Logic
126
- """,
127
  ),
128
  ("placeholder", "{messages}"),
129
  ]
@@ -133,38 +237,7 @@ script_writer_prompt = ChatPromptTemplate.from_messages(
133
  [
134
  (
135
  "system",
136
- """
137
- Vai trò: Bạn là Script Writer dựa trên các nội dung, insight được cung cấp.
138
- Instruction:
139
- - Viết lại từng phần dựa theo outline mới, dữ liệu nghiên cứu, insight comment, giữ văn liền mạch - cảm xúc - kể chuyện, format cho video YouTube (dạng văn nói, không dùng icon, chỉ text).
140
- - Viết theo hội thoại chỉ có một người nói, không có người khác.
141
-
142
- Input:
143
- - Output từ Script Re-Outline Agent (Important)
144
- - Output từ Scientific Fact Finder Agent
145
- - Output từ Comment Insight Extractor Agent
146
-
147
- Processing:
148
- - Sau khi viết 1 phần, ngừng ngay.
149
- - Output phải liền mạch, không có gạch đầu dòng.
150
- - Tone giọng thân thiện, kể truyện, truyền cảm xúc, không dùng icon, chỉ dùng text.
151
- - Cài hook cảm xúc, ví dụ thực tế
152
- - Kể mở ra CTA hoặc dẫn sang phần tiếp theo.
153
- - Có câu hỏi tu từ nhẹ nhàng
154
- - Nhắc lại lợi ích quan trọng
155
- - So sánh "thay vì... thì..." để khán giả thấy rõ "why"
156
- - Không dùng icon, emoji
157
- - Kết thúc phải là kết thúc mở đề người dùng có thể yêu cầu viết tiếp thay vì kết thúc sau khi hoàn thành đủ hook, thân bài, điểm chốt, CTA.
158
- Output:
159
- - Title: Tên của phần nội dung
160
- - Content: Script content
161
-
162
- Lưu ý:
163
- - Chỉ gen ra một phần nội dung.
164
- - Script được gen phả bám sát cấu trúc và có tính liền mạch, không được lủng củng, lăp lại nội dung.
165
- - Nếu user nhập 'ok, viết cho tôi phần tiếp theo, bám sát cấu trúc, số lượng từ cho mỗi mục trong outline, các công thức tạo cảm xúc và đừng quên đối tượng khán giả là người Mỹ,giới tính nữ, trên 20 tuổi, bắt đầu, trình bày thành dạng câu văn liền mạch, dùng để làm văn nói cho video YouTube, không dùng icon' thì tiếp tục viết tiếp.
166
-
167
- """,
168
  ),
169
  ("placeholder", "{messages}"),
170
  ]
@@ -173,11 +246,23 @@ Lưu ý:
173
 
174
  chain_script_structure_analyzer = script_structure_analyzer_prompt | llm
175
  chain_comment_insight_extractor = comment_insight_extractor_prompt | llm
176
- scientific_fact_agent = create_react_agent(
177
- model=llm,
178
- tools=[duckduckgo_search],
179
- prompt=scientific_fact_finder_prompt,
180
- )
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
 
183
  chain_script_re_outline = script_re_outline_prompt | llm
 
1
+ # from langchain_core.prompts import ChatPromptTemplate
2
+ # from src.config.llm import llm_2_0 as llm, llm_2_5_flash_preview
3
+ # from pydantic import BaseModel, Field
4
+ # from langchain_community.tools import DuckDuckGoSearchResults
5
+ # from langgraph.prebuilt import create_react_agent
6
+
7
+ # duckduckgo_search = DuckDuckGoSearchResults(max_results=10, output_format="json")
8
+
9
+ # script_structure_analyzer_prompt = ChatPromptTemplate.from_messages(
10
+ # [
11
+ # (
12
+ # "system",
13
+ # """
14
+ # Vai trò: Bạn là Script Structure Analyzer trong một workflow của một nhóm các agent.
15
+ # Instruction:
16
+ # - Tự động phân tích kịch bản gốc, tách các phần (Mở bài, Thân bài, Điểm chốt, CTA)
17
+ # - Xác định công thức cấu trúc (AIDA, PAS, BFB,...)
18
+ # - Trích xuất hook, câu chuyển đoạn, CTA
19
+ # - Phát hiện điểm mạnh/yếu/chỗ lạc nhịp
20
+
21
+ # Input: Script gốc
22
+ # Output:
23
+ # - Outline:
24
+ # - Mở bài
25
+ # - Thân bài
26
+ # - Điểm chốt
27
+ # - CTA
28
+ # - Công thức cấu trúc
29
+ # - AIDA: Attention, Interest, Desire, Action
30
+ # - PAS: Problem, Agitation, Solution
31
+ # - BFB: Belief, Feeling, Behavior
32
+ # - Hook
33
+ # - Câu chuyển đoạn
34
+ # - CTA
35
+ # - Điểm mạnh/yếu/chỗ lạc nhịp
36
+ # """,
37
+ # ),
38
+ # ("user", "input script: {script}"),
39
+ # ]
40
+ # )
41
+
42
+ # comment_insight_extractor_prompt = ChatPromptTemplate.from_messages(
43
+ # [
44
+ # (
45
+ # "system",
46
+ # """
47
+ # Vai trò: Bạn là Comment Insight Extractor trong một workflow của một nhóm các agent phân tích youtube video.
48
+ # Instruction:
49
+ # - Đọc, phân tích tất cả comment, trích xuất insight
50
+ # - lọc ra các câu hỏi lặp lại, nỗi sợ/mong muốn/lợi ích/ngôn ngữ quen thuộc
51
+ # - So sánh insight với script gốc và xác định thiếu sót.
52
+
53
+ # Input:
54
+ # - Output từ Script Structure Analyzer Agent Youtube Video
55
+ # - Comment
56
+
57
+ # Output:
58
+ # - Insights Table:
59
+ # - Insight
60
+ # - Original Comment
61
+ # - Pain or Benefit
62
+ # - Suggest for Script
63
+ # - Missing From Script
64
+ # - Repeated Questions
65
+ # - Audience Language
66
+
67
+ # """,
68
+ # ),
69
+ # ("user", "input comment: {comment}"),
70
+ # (
71
+ # "user",
72
+ # "input script_structure_analyzer_response: {script_structure_analyzer_response}",
73
+ # ),
74
+ # ]
75
+ # )
76
+ # scientific_fact_finder_prompt = ChatPromptTemplate.from_messages(
77
+ # [
78
+ # (
79
+ # "system",
80
+ # """
81
+ # Vai trò: Bạn là Scientific Fact Finder trong một workflow của một nhóm các agent phân tích youtube video.
82
+ # Instruction:
83
+ # - Tự động research 3-5 nghiên cứu khoa học thực tế (PubMed, JAMA, Circulation, Nutrients…), tóm tắt số liệu, trích nguồn, gợi ý số liệu phù hợp cho từng đoạn trong script mới.
84
+ # - So sánh fact science với script gốc và xác định thiếu sót.
85
+
86
+ # Input:
87
+ # - Output từ Script Structure Analyzer Agent Youtube Video
88
+ # - Output từ Comment Insight Extractor Agent Youtube Video
89
+
90
+ # Output List:
91
+ # - Title: Tên nghiên cứu
92
+ # - Summary: Tóm tắt nghiên cứu
93
+ # - Source: Nguồn nghiên cứu
94
+ # - Relevant for Section: Relevant cho section nào trong script mới
95
+ # """,
96
+ # ),
97
+ # ("placeholder", "{messages}"),
98
+ # ]
99
+ # )
100
+
101
+ # script_re_outline_prompt = ChatPromptTemplate.from_messages(
102
+ # [
103
+ # (
104
+ # "system",
105
+ # """
106
+ # Vai trò: Bạn là Script Re-Outline Agent trong một workflow của một nhóm các agent.
107
+ # Instruction:
108
+ # Kết hợp outline cũ, insight từ comment, fact từ research để lập outline mới: Hook mới, thứ tự section mới, CTA mới, các ý chuyển mạch rõ ràng, phân bổ fact/nghiên cứu vào các section.
109
+
110
+ # Input:
111
+ # - Output từ Script Structure Analyzer Agent
112
+ # - Output từ Comment Insight Extractor Agent
113
+ # - Output từ Scientific Fact Finder Agent
114
+
115
+ # Output:
116
+
117
+ # - Outline mới: (Section, summary, suggested length, facts to include)
118
+ # - Hook mở bài
119
+ # - Thân bài 1
120
+ # - Thân bài 2
121
+ # - Điểm chốt
122
+ # - CTA
123
+ # - CTA position
124
+ # - Transitions
125
+ # - Order Logic
126
+ # """,
127
+ # ),
128
+ # ("placeholder", "{messages}"),
129
+ # ]
130
+ # )
131
+
132
+ # script_writer_prompt = ChatPromptTemplate.from_messages(
133
+ # [
134
+ # (
135
+ # "system",
136
+ # """
137
+ # Vai trò: Bạn là Script Writer dựa trên các nội dung, insight được cung cấp.
138
+ # Instruction:
139
+ # - Viết lại từng phần dựa theo outline mới, dữ liệu nghiên cứu, insight comment, giữ văn liền mạch - cảm xúc - kể chuyện, format cho video YouTube (dạng văn nói, không dùng icon, chỉ text).
140
+ # - Viết theo hội thoại chỉ có một người nói, không có người khác.
141
+
142
+ # Input:
143
+ # - Output từ Script Re-Outline Agent (Important)
144
+ # - Output từ Scientific Fact Finder Agent
145
+ # - Output từ Comment Insight Extractor Agent
146
+
147
+ # Processing:
148
+ # - Sau khi viết 1 phần, ngừng ngay.
149
+ # - Output phải liền mạch, không có gạch đầu dòng.
150
+ # - Tone giọng thân thiện, kể truyện, truyền cảm xúc, không dùng icon, chỉ dùng text.
151
+ # - Cài hook cảm xúc, ví dụ thực tế
152
+ # - Kể mở ra CTA hoặc dẫn sang phần tiếp theo.
153
+ # - Có câu hỏi tu từ nhẹ nhàng
154
+ # - Nhắc lại lợi ích quan trọng
155
+ # - So sánh "thay vì... thì..." để khán giả thấy rõ "why"
156
+ # - Không dùng icon, emoji
157
+ # - Kết thúc phải là kết thúc mở đề người dùng có thể yêu cầu viết tiếp thay vì kết thúc sau khi hoàn thành đủ hook, thân bài, điểm chốt, CTA.
158
+ # Output:
159
+ # - Title: Tên của phần nội dung
160
+ # - Content: Script content
161
+
162
+ # Lưu ý:
163
+ # - Chỉ gen ra một phần nội dung.
164
+ # - Script được gen phả bám sát cấu trúc và có tính liền mạch, không được lủng củng, lăp lại nội dung.
165
+ # - Nếu user nhập 'ok, viết cho tôi phần tiếp theo, bám sát cấu trúc, số lượng từ cho mỗi mục trong outline, các công thức tạo cảm xúc và đừng quên đối tượng khán giả là người Mỹ,giới tính nữ, trên 20 tuổi, bắt đầu, trình bày thành dạng câu văn liền mạch, dùng để làm văn nói cho video YouTube, không dùng icon' thì tiếp tục viết tiếp.
166
+
167
+ # """,
168
+ # ),
169
+ # ("placeholder", "{messages}"),
170
+ # ]
171
+ # )
172
+
173
+
174
+ # chain_script_structure_analyzer = script_structure_analyzer_prompt | llm
175
+ # chain_comment_insight_extractor = comment_insight_extractor_prompt | llm
176
+ # scientific_fact_agent = create_react_agent(
177
+ # model=llm,
178
+ # tools=[duckduckgo_search],
179
+ # prompt=scientific_fact_finder_prompt,
180
+ # )
181
+
182
+
183
+ # chain_script_re_outline = script_re_outline_prompt | llm
184
+ # chain_script_writer = script_writer_prompt | llm_2_5_flash_preview
185
  from langchain_core.prompts import ChatPromptTemplate
186
  from src.config.llm import llm_2_0 as llm, llm_2_5_flash_preview
187
  from pydantic import BaseModel, Field
 
194
  [
195
  (
196
  "system",
197
+ "{prompt}",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  ),
199
  ("user", "input script: {script}"),
200
  ]
 
204
  [
205
  (
206
  "system",
207
+ "{prompt}",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  ),
209
  ("user", "input comment: {comment}"),
210
  (
 
217
  [
218
  (
219
  "system",
220
+ "{prompt}",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  ),
222
  ("placeholder", "{messages}"),
223
  ]
 
227
  [
228
  (
229
  "system",
230
+ "{prompt}",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  ),
232
  ("placeholder", "{messages}"),
233
  ]
 
237
  [
238
  (
239
  "system",
240
+ "{prompt}",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  ),
242
  ("placeholder", "{messages}"),
243
  ]
 
246
 
247
  chain_script_structure_analyzer = script_structure_analyzer_prompt | llm
248
  chain_comment_insight_extractor = comment_insight_extractor_prompt | llm
249
+
250
+
251
+ def scientific_fact_finder_agent(prompt: str):
252
+ prompt_template = ChatPromptTemplate.from_messages(
253
+ [
254
+ (
255
+ "system",
256
+ "{prompt}",
257
+ ),
258
+ ("placeholder", "{messages}"),
259
+ ]
260
+ ).partial(prompt=prompt)
261
+ return create_react_agent(
262
+ model=llm,
263
+ tools=[duckduckgo_search],
264
+ prompt=prompt_template,
265
+ )
266
 
267
 
268
  chain_script_re_outline = script_re_outline_prompt | llm
src/apis/__pycache__/create_app.cpython-311.pyc CHANGED
Binary files a/src/apis/__pycache__/create_app.cpython-311.pyc and b/src/apis/__pycache__/create_app.cpython-311.pyc differ
 
src/apis/controllers/__pycache__/auth_controller.cpython-311.pyc ADDED
Binary file (1.99 kB). View file
 
src/apis/controllers/auth_controller.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import HTTPException, status
2
+ from src.apis.models.user_models import User
3
+ from src.config.mongo import UserCRUD
4
+ from src.apis.providers.jwt_provider import JWTProvider
5
+ from src.utils.logger import logger
6
+ import jwt
7
+
8
+ jwt_provider = JWTProvider()
9
+
10
+
11
+ async def login_control(username: str, password: str):
12
+
13
+ user = User(username=username, password=password)
14
+ existing_user = await UserCRUD.read_one({"username": user.username})
15
+ if not existing_user:
16
+ raise HTTPException(
17
+ status_code=status.HTTP_401_UNAUTHORIZED,
18
+ detail="Invalid username or password",
19
+ )
20
+ if existing_user and existing_user["password"] != user.password:
21
+ raise HTTPException(
22
+ status_code=status.HTTP_401_UNAUTHORIZED,
23
+ detail="Invalid username or password",
24
+ )
25
+
26
+ token = jwt_provider.encrypt({"id": str(existing_user["_id"])})
27
+ user_data = user.__dict__
28
+ user_data["id"] = existing_user["_id"]
29
+ user_data["username"] = existing_user["username"]
30
+ user_data.pop("password", None)
31
+ user_data.pop("created_at", None)
32
+ user_data.pop("updated_at", None)
33
+ user_data.pop("expire_at", None)
34
+ return token, user_data
35
+
36
+
src/apis/create_app.py CHANGED
@@ -1,11 +1,13 @@
1
  from fastapi import FastAPI, APIRouter
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from src.apis.routers.gen_script import router as gen_script_router
4
-
 
5
 
6
  api_router = APIRouter()
7
  api_router.include_router(gen_script_router)
8
-
 
9
 
10
  def create_app():
11
  app = FastAPI(
 
1
  from fastapi import FastAPI, APIRouter
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from src.apis.routers.gen_script import router as gen_script_router
4
+ from src.apis.routers.auth_router import router as auth_router
5
+ from src.apis.routers.prompt_editor import router as prompt_editor_router
6
 
7
  api_router = APIRouter()
8
  api_router.include_router(gen_script_router)
9
+ api_router.include_router(auth_router)
10
+ api_router.include_router(prompt_editor_router)
11
 
12
  def create_app():
13
  app = FastAPI(
src/apis/interfaces/__pycache__/auth_interface.cpython-311.pyc CHANGED
Binary files a/src/apis/interfaces/__pycache__/auth_interface.cpython-311.pyc and b/src/apis/interfaces/__pycache__/auth_interface.cpython-311.pyc differ
 
src/apis/interfaces/auth_interface.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class Credential(BaseModel):
5
+ credential: str = Field(..., example="F9P/3?@q2!vq")
6
+
7
+
8
+ class _LoginResponseInterface(BaseModel):
9
+ token: str = Field(..., title="JWT Token")
10
+
11
+
12
+ class LoginResponseInterface(BaseModel):
13
+ msg: str = Field(..., title="Message")
14
+ data: _LoginResponseInterface = Field(..., title="User Data")
15
+
16
+
17
+ class AuthInterface(BaseModel):
18
+ gtoken: str = Field(..., title="Google Access-Token")
src/apis/middlewares/__pycache__/auth_middleware.cpython-311.pyc CHANGED
Binary files a/src/apis/middlewares/__pycache__/auth_middleware.cpython-311.pyc and b/src/apis/middlewares/__pycache__/auth_middleware.cpython-311.pyc differ
 
src/apis/middlewares/auth_middleware.py CHANGED
@@ -29,8 +29,6 @@ async def get_current_user(
29
  content={"msg": "Authentication failed"}, status_code=401
30
  )
31
  user = await UserCRUD.read_one({"_id": ObjectId(user_id)})
32
- user_email = user.get("email", None)
33
- logger.info(f"Request of user: {user_email}")
34
  if not user:
35
  return JSONResponse(
36
  content={"msg": "Authentication failed"}, status_code=401
 
29
  content={"msg": "Authentication failed"}, status_code=401
30
  )
31
  user = await UserCRUD.read_one({"_id": ObjectId(user_id)})
 
 
32
  if not user:
33
  return JSONResponse(
34
  content={"msg": "Authentication failed"}, status_code=401
src/apis/models/__pycache__/BaseDocument.cpython-311.pyc CHANGED
Binary files a/src/apis/models/__pycache__/BaseDocument.cpython-311.pyc and b/src/apis/models/__pycache__/BaseDocument.cpython-311.pyc differ
 
src/apis/models/__pycache__/prompt_models.cpython-311.pyc ADDED
Binary file (1.42 kB). View file
 
src/apis/models/__pycache__/user_models.cpython-311.pyc CHANGED
Binary files a/src/apis/models/__pycache__/user_models.cpython-311.pyc and b/src/apis/models/__pycache__/user_models.cpython-311.pyc differ
 
src/apis/models/prompt_models.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import Field, EmailStr
2
+ from .BaseDocument import BaseDocument
3
+ from bson import ObjectId
4
+
5
+
6
+ class Prompt(BaseDocument):
7
+ id: str = Field("", description="Prompt's id")
8
+ script_structure_analyzer_prompt: str = Field(None, description="Script Structure Analyzer Prompt")
9
+ comment_insight_extractor_prompt: str = Field(None, description="Comment Insight Extractor Prompt")
10
+ scientific_fact_finder_prompt: str = Field(None, description="Scientific Fact Finder Prompt")
11
+ script_re_outline_prompt: str = Field(None, description="Script Re-Outline Prompt")
12
+ script_writer_prompt: str = Field(None, description="Script Writer Prompt")
13
+
14
+
src/apis/models/user_models.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import Field, EmailStr
2
+ from .BaseDocument import BaseDocument
3
+ from bson import ObjectId
4
+
5
+
6
+ def get_user(user) -> dict:
7
+ return {
8
+ "id": str(user["_id"]),
9
+ "username": user["username"],
10
+ "password": user["password"],
11
+ }
12
+
13
+
14
+ def list_serial(users) -> list:
15
+ return [get_user(user) for user in users]
16
+
17
+
18
+ class User(BaseDocument):
19
+ id: str = Field("", description="User's id")
20
+ username: str = Field("", description="User's username")
21
+ password: str = Field("", description="User's password")
22
+
23
+ class Config:
24
+ json_schema_extra = {
25
+ "example": {
26
+ "username": "johnUS192",
27
+ "password": "1234567890",
28
+ }
29
+ }
src/apis/providers/__pycache__/jwt_provider.cpython-311.pyc CHANGED
Binary files a/src/apis/providers/__pycache__/jwt_provider.cpython-311.pyc and b/src/apis/providers/__pycache__/jwt_provider.cpython-311.pyc differ
 
src/apis/providers/jwt_provider.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import AnyStr, Dict, Union
2
+ import os
3
+ from fastapi import HTTPException, status
4
+ from jose import jwt, JWTError
5
+
6
+
7
+ class JWTProvider:
8
+ """
9
+ Perform JWT Encryption and Decryption
10
+ """
11
+
12
+ def __init__(
13
+ self, secret: AnyStr = os.environ.get("JWT_SECRET"), algorithm: AnyStr = "HS256"
14
+ ):
15
+ self.secret = secret
16
+ self.algorithm = algorithm
17
+
18
+ def encrypt(self, data: Dict) -> AnyStr:
19
+ """
20
+ Encrypt the data with JWT
21
+ """
22
+ return jwt.encode(data, self.secret, algorithm=self.algorithm)
23
+
24
+ def decrypt(self, token: AnyStr) -> Union[Dict, None]:
25
+ """
26
+ Decrypt the token with JWT
27
+ """
28
+ try:
29
+ return jwt.decode(token, self.secret, algorithms=[self.algorithm])
30
+ except JWTError as e:
31
+ raise HTTPException(
32
+ status_code=status.HTTP_401_UNAUTHORIZED,
33
+ detail=f"Could not validate credentials. {str(e)}",
34
+ )
35
+
36
+
37
+ jwt_provider = JWTProvider()
src/apis/routers/__pycache__/auth_router.cpython-311.pyc CHANGED
Binary files a/src/apis/routers/__pycache__/auth_router.cpython-311.pyc and b/src/apis/routers/__pycache__/auth_router.cpython-311.pyc differ
 
src/apis/routers/__pycache__/gen_script.cpython-311.pyc CHANGED
Binary files a/src/apis/routers/__pycache__/gen_script.cpython-311.pyc and b/src/apis/routers/__pycache__/gen_script.cpython-311.pyc differ
 
src/apis/routers/__pycache__/prompt_editor.cpython-311.pyc ADDED
Binary file (4.5 kB). View file
 
src/apis/routers/auth_router.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, status, Depends
2
+ from fastapi.responses import JSONResponse
3
+ from typing import Annotated
4
+ from src.apis.models.user_models import User
5
+ from src.apis.controllers.auth_controller import (
6
+ login_control,
7
+ )
8
+ from src.apis.middlewares.auth_middleware import get_current_user
9
+ from pydantic import BaseModel, Field
10
+ from src.utils.logger import logger
11
+
12
+ router = APIRouter(prefix="/auth", tags=["Authentications"])
13
+
14
+ user_dependency = Annotated[User, Depends(get_current_user)]
15
+
16
+
17
+ class LoginRequest(BaseModel):
18
+ username: str = Field(..., description="Username")
19
+ password: str = Field(..., description="Password")
20
+
21
+ model_config = {
22
+ "json_schema_extra": {
23
+ "example": {
24
+ "username": "johnUS192",
25
+ "password": "1234567890",
26
+ }
27
+ }
28
+ }
29
+
30
+
31
+ @router.post("/login", status_code=status.HTTP_200_OK)
32
+ async def login(body: LoginRequest):
33
+ try:
34
+ logger.info(f"User {body.username} is logging in.")
35
+ token, user_data = await login_control(body.username, body.password)
36
+
37
+ return JSONResponse(
38
+ content={
39
+ "token": token,
40
+ "user_data": user_data,
41
+ },
42
+ status_code=200,
43
+ )
44
+ except Exception as e:
45
+ return JSONResponse(content={"message": str(e)}, status_code=500)
src/apis/routers/gen_script.py CHANGED
@@ -1,17 +1,24 @@
1
- from fastapi import APIRouter
2
  from fastapi.responses import StreamingResponse
3
  from langchain_core.messages import AIMessageChunk
4
  from langchain_core.runnables import RunnableConfig
5
  from src.agents.agent_transcript.flow import script_writer_agent
6
  from src.utils.logger import logger
7
- from pydantic import BaseModel
8
  import json
9
  import asyncio
 
 
 
 
 
10
 
11
 
12
  class GenScriptRequest(BaseModel):
13
- video_link: str
14
- target_word_count: int = 50000 # Default 2500 words
 
 
15
 
16
 
17
  router = APIRouter()
@@ -50,48 +57,66 @@ async def message_generator(
50
  # Stream state updates
51
  state_data = {"type": "state_update", "state": event_message}
52
  last_output_state = event_message
53
-
54
  # Handle specific data extractions
55
- if "transcript" in event_message and event_message["transcript"]:
 
 
 
56
  transcript_data = {
57
  "type": "transcript_extracted",
58
- "transcript": event_message["transcript"][:500] + "..." if len(event_message["transcript"]) > 500 else event_message["transcript"],
59
- "full_length": len(event_message["transcript"])
 
 
 
 
60
  }
61
  yield f"data: {json.dumps(transcript_data)}\n\n"
62
-
63
  if "comment" in event_message and event_message["comment"]:
64
  comment_data = {
65
- "type": "comment_extracted",
66
- "comment": event_message["comment"][:500] + "..." if len(event_message["comment"]) > 500 else event_message["comment"],
67
- "full_length": len(event_message["comment"])
 
 
 
 
68
  }
69
  yield f"data: {json.dumps(comment_data)}\n\n"
70
-
71
  if "script_count" in event_message:
72
  script_count_data = {
73
  "type": "script_count_calculated",
74
  "script_count": event_message["script_count"],
75
- "target_word_count": event_message.get("target_word_count", 8000)
 
 
76
  }
77
  yield f"data: {json.dumps(script_count_data)}\n\n"
78
-
79
  # Handle individual script updates
80
- if "script_writer_response" in event_message and "current_script_index" in event_message:
 
 
 
81
  current_scripts = event_message["script_writer_response"]
82
  current_index = event_message["current_script_index"]
83
  script_count = event_message.get("script_count", 10)
84
-
85
  if current_scripts:
86
  individual_script_data = {
87
  "type": "individual_script",
88
  "script_index": current_index,
89
- "script_content": current_scripts[-1] if current_scripts else "",
 
 
90
  "progress": f"{current_index}/{script_count}",
91
- "scripts": current_scripts
92
  }
93
  yield f"data: {json.dumps(individual_script_data)}\n\n"
94
-
95
  yield f"data: {json.dumps(state_data, default=str)}\n\n"
96
 
97
  except Exception as e:
@@ -121,14 +146,14 @@ async def message_generator(
121
 
122
 
123
  @router.post("/gen-script")
124
- async def gen_script(request: GenScriptRequest):
125
  """
126
  Generate scripts with streaming response
127
  """
128
  config = RunnableConfig()
129
  input_graph = {
130
  "video_link": request.video_link,
131
- "target_word_count": request.target_word_count
132
  }
133
 
134
  return StreamingResponse(
@@ -140,19 +165,3 @@ async def gen_script(request: GenScriptRequest):
140
  "Content-Type": "text/event-stream",
141
  },
142
  )
143
-
144
-
145
- @router.post("/gen-script-sync")
146
- def gen_script_sync(request: GenScriptRequest):
147
- """
148
- Generate scripts with synchronous response (non-streaming)
149
- """
150
- response = script_writer_agent.invoke({
151
- "video_link": request.video_link,
152
- "target_word_count": request.target_word_count
153
- })
154
- return {
155
- "scripts": response.get("script_writer_response", []),
156
- "total_scripts": len(response.get("script_writer_response", [])),
157
- "full_response": response,
158
- }
 
1
+ from fastapi import APIRouter, Depends
2
  from fastapi.responses import StreamingResponse
3
  from langchain_core.messages import AIMessageChunk
4
  from langchain_core.runnables import RunnableConfig
5
  from src.agents.agent_transcript.flow import script_writer_agent
6
  from src.utils.logger import logger
7
+ from pydantic import BaseModel, Field
8
  import json
9
  import asyncio
10
+ from src.apis.middlewares.auth_middleware import get_current_user
11
+ from typing import Annotated
12
+ from src.apis.models.user_models import User
13
+
14
+ user_dependency = Annotated[User, Depends(get_current_user)]
15
 
16
 
17
  class GenScriptRequest(BaseModel):
18
+ video_link: str = Field(..., description="Video link")
19
+ target_word_count: int = Field(
20
+ 2500, ge=2000, le=12000, description="Target word count"
21
+ )
22
 
23
 
24
  router = APIRouter()
 
57
  # Stream state updates
58
  state_data = {"type": "state_update", "state": event_message}
59
  last_output_state = event_message
60
+
61
  # Handle specific data extractions
62
+ if (
63
+ "transcript" in event_message
64
+ and event_message["transcript"]
65
+ ):
66
  transcript_data = {
67
  "type": "transcript_extracted",
68
+ "transcript": (
69
+ event_message["transcript"][:500] + "..."
70
+ if len(event_message["transcript"]) > 500
71
+ else event_message["transcript"]
72
+ ),
73
+ "full_length": len(event_message["transcript"]),
74
  }
75
  yield f"data: {json.dumps(transcript_data)}\n\n"
76
+
77
  if "comment" in event_message and event_message["comment"]:
78
  comment_data = {
79
+ "type": "comment_extracted",
80
+ "comment": (
81
+ event_message["comment"][:500] + "..."
82
+ if len(event_message["comment"]) > 500
83
+ else event_message["comment"]
84
+ ),
85
+ "full_length": len(event_message["comment"]),
86
  }
87
  yield f"data: {json.dumps(comment_data)}\n\n"
88
+
89
  if "script_count" in event_message:
90
  script_count_data = {
91
  "type": "script_count_calculated",
92
  "script_count": event_message["script_count"],
93
+ "target_word_count": event_message.get(
94
+ "target_word_count", 8000
95
+ ),
96
  }
97
  yield f"data: {json.dumps(script_count_data)}\n\n"
98
+
99
  # Handle individual script updates
100
+ if (
101
+ "script_writer_response" in event_message
102
+ and "current_script_index" in event_message
103
+ ):
104
  current_scripts = event_message["script_writer_response"]
105
  current_index = event_message["current_script_index"]
106
  script_count = event_message.get("script_count", 10)
107
+
108
  if current_scripts:
109
  individual_script_data = {
110
  "type": "individual_script",
111
  "script_index": current_index,
112
+ "script_content": (
113
+ current_scripts[-1] if current_scripts else ""
114
+ ),
115
  "progress": f"{current_index}/{script_count}",
116
+ "scripts": current_scripts,
117
  }
118
  yield f"data: {json.dumps(individual_script_data)}\n\n"
119
+
120
  yield f"data: {json.dumps(state_data, default=str)}\n\n"
121
 
122
  except Exception as e:
 
146
 
147
 
148
  @router.post("/gen-script")
149
+ async def gen_script(request: GenScriptRequest, user: user_dependency):
150
  """
151
  Generate scripts with streaming response
152
  """
153
  config = RunnableConfig()
154
  input_graph = {
155
  "video_link": request.video_link,
156
+ "target_word_count": request.target_word_count,
157
  }
158
 
159
  return StreamingResponse(
 
165
  "Content-Type": "text/event-stream",
166
  },
167
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/apis/routers/prompt_editor.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, status, Depends
2
+ from fastapi.responses import JSONResponse
3
+ from typing import Annotated
4
+ from src.apis.models.user_models import User
5
+ from src.apis.controllers.auth_controller import (
6
+ login_control,
7
+ )
8
+ from src.apis.middlewares.auth_middleware import get_current_user
9
+ from pydantic import BaseModel, Field
10
+ from src.utils.logger import logger
11
+ from src.config.mongo import PromptCRUD
12
+ from bson import ObjectId
13
+
14
+ router = APIRouter(prefix="/prompt", tags=["Prompt Editor"])
15
+
16
+ user_dependency = Annotated[User, Depends(get_current_user)]
17
+
18
+
19
+ @router.get("/list", status_code=status.HTTP_200_OK)
20
+ async def list_prompt(user: user_dependency):
21
+ try:
22
+ logger.info(f"User {user['username']} is listing prompts.")
23
+ prompts = await PromptCRUD.read({})
24
+ for prompt in prompts:
25
+ prompt.pop("created_at")
26
+ prompt.pop("updated_at")
27
+ prompt.pop("expire_at")
28
+ return JSONResponse(content=prompts, status_code=status.HTTP_200_OK)
29
+ except Exception as e:
30
+ return JSONResponse(content={"message": str(e)}, status_code=500)
31
+
32
+
33
+ class UpdatePromptRequest(BaseModel):
34
+ id: str = Field(..., description="Prompt's id")
35
+ script_writer_prompt: str = Field(None, description="Script Writer Prompt")
36
+ script_re_outline_prompt: str = Field(None, description="Script Re-Outline Prompt")
37
+ scientific_fact_finder_prompt: str = Field(None, description="Scientific Fact Finder Prompt")
38
+ comment_insight_extractor_prompt: str = Field(None, description="Comment Insight Extractor Prompt")
39
+ script_structure_analyzer_prompt: str = Field(None, description="Script Structure Analyzer Prompt")
40
+
41
+
42
+ @router.put("/update", status_code=status.HTTP_200_OK)
43
+ async def update_prompt(user: user_dependency, body: UpdatePromptRequest):
44
+ try:
45
+ logger.info(f"User {user['username']} is updating prompt {body.id}.")
46
+ await PromptCRUD.update(
47
+ {"_id": ObjectId(body.id)},
48
+ {"$set": body.model_dump(exclude_none=True)},
49
+ )
50
+ return JSONResponse(
51
+ content={"message": "Prompt updated successfully"},
52
+ status_code=status.HTTP_200_OK,
53
+ )
54
+ except Exception as e:
55
+ return JSONResponse(content={"message": str(e)}, status_code=500)
src/config/__pycache__/mongo.cpython-311.pyc CHANGED
Binary files a/src/config/__pycache__/mongo.cpython-311.pyc and b/src/config/__pycache__/mongo.cpython-311.pyc differ
 
src/config/mongo.py CHANGED
@@ -10,7 +10,7 @@ import os
10
 
11
  client: AsyncIOMotorClient = AsyncIOMotorClient(os.getenv("MONGO_CONNECTION_STR"))
12
  # database = client["custom_gpt"]
13
- database = client["ai_store"]
14
 
15
 
16
  class MongoCRUD:
@@ -175,16 +175,8 @@ class MongoCRUD:
175
  return docs
176
 
177
 
178
- from src.apis.models.bot_models import Bot
179
  from src.apis.models.user_models import User
180
- from src.apis.models.grade_models import GradedAssignment
181
- from src.apis.models.service_provide import ServiceProvider
182
- from src.apis.models.category_models import Category
183
- from src.apis.models.order_models import Order
184
-
185
- bot_crud = MongoCRUD(database["bot"], Bot)
186
- UserCRUD = MongoCRUD(database["user"], User)
187
- GradedAssignmentCRUD = MongoCRUD(database["graded_assignments"], GradedAssignment)
188
- ServiceCRUD = MongoCRUD(database["services"], ServiceProvider)
189
- CategoryCRUD = MongoCRUD(database["categories"], Category)
190
- OrderCRUD = MongoCRUD(database["orders"], Order)
 
10
 
11
  client: AsyncIOMotorClient = AsyncIOMotorClient(os.getenv("MONGO_CONNECTION_STR"))
12
  # database = client["custom_gpt"]
13
+ database = client["prompt_editor"]
14
 
15
 
16
  class MongoCRUD:
 
175
  return docs
176
 
177
 
 
178
  from src.apis.models.user_models import User
179
+ from src.apis.models.prompt_models import Prompt
180
+
181
+ UserCRUD = MongoCRUD(database["users"], User)
182
+ PromptCRUD = MongoCRUD(database["prompt_templates"], Prompt)
 
 
 
 
 
 
 
src/utils/__pycache__/helper.cpython-311.pyc CHANGED
Binary files a/src/utils/__pycache__/helper.cpython-311.pyc and b/src/utils/__pycache__/helper.cpython-311.pyc differ
 
src/utils/helper.py CHANGED
@@ -178,6 +178,7 @@ def extract_transcript(video_link: str):
178
  raise
179
 
180
 
 
181
  def extract_comment(video_link: str):
182
  ytd_api = YoutubeCommentDownloader()
183
  comments = ytd_api.get_comments_from_url(video_link)
 
178
  raise
179
 
180
 
181
+
182
  def extract_comment(video_link: str):
183
  ytd_api = YoutubeCommentDownloader()
184
  comments = ytd_api.get_comments_from_url(video_link)