feat(feedback): Add content improvement feedback system

Frontend (frontend/app.js):

- Add textarea for improvement feedback

- Add submit button with loading state

- Handle API response and display improved content

Backend (backend/copywriter.py):

- Add improve_copy() method using Cohere API

- Integrate retry mechanism for API calls

Backend (backend/main.py):

- Add /improve-content POST endpoint

- Implement error handling and return improved content with metadata

Testing:

- Verified feedback submission flow

- Confirmed improved content generation

- Tested error scenarios and loading states
This commit is contained in:
Michael Ikehi
2025-04-18 19:19:10 +01:00
parent 12e0830ba6
commit 71ad7b4d26
8 changed files with 790 additions and 91 deletions
+86
View File
@@ -882,3 +882,89 @@
2025-04-18 17:41:55.046 | INFO | copywriter:generate_copy:90 - Generated content with 2070 characters
2025-04-18 17:41:55.458 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 17:41:55.458 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:11:18.236 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:11:18.236 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:11:40.648 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:11:40.648 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:13:01.347 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:13:01.347 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:36:18.449 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418164155 not found
2025-04-18 18:36:18.449 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418164155 not found
2025-04-18 18:36:43.730 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418161237 not found
2025-04-18 18:36:43.730 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418161237 not found
2025-04-18 18:37:32.259 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API:
2025-04-18 18:37:32.259 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API:
2025-04-18 18:38:06.509 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API:
2025-04-18 18:38:06.509 | ERROR | copywriter:_call_llm_api:139 - Error calling Cohere API:
2025-04-18 18:38:48.267 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:38:48.267 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:38:48.272 | INFO | copywriter:generate_copy:90 - Generated content with 3812 characters
2025-04-18 18:38:48.272 | INFO | copywriter:generate_copy:90 - Generated content with 3812 characters
2025-04-18 18:38:51.235 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:38:51.235 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:39:59.364 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found
2025-04-18 18:39:59.364 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found
2025-04-18 18:40:23.978 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found
2025-04-18 18:40:23.978 | ERROR | main:get_user_query:437 - Error getting user query: 404: Query with timestamp 20250418173851 not found
2025-04-18 18:43:01.011 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:43:01.011 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:43:07.295 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))?
2025-04-18 18:43:07.295 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))?
2025-04-18 18:44:21.955 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:44:21.955 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:44:28.293 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted
2025-04-18 18:44:28.293 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted
2025-04-18 18:44:32.713 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))?
2025-04-18 18:44:32.713 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))?
2025-04-18 18:47:11.756 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:47:11.756 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:47:12.100 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:47:12.100 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:47:21.198 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))?
2025-04-18 18:47:21.198 | ERROR | main:get_training_data:306 - Error retrieving training data: Column expression, FROM clause, or other columns clause element expected, got [Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None)]. Did you mean to say select(Table('training_data', MetaData(), Column('id', Integer(), table=<training_data>, primary_key=True, nullable=False), Column('content', String(), table=<training_data>, nullable=False), Column('content_type', String(), table=<training_data>, nullable=False), Column('metadata', JSON(), table=<training_data>, nullable=False), Column('added_at', DateTime(), table=<training_data>, nullable=False, default=CallableColumnDefault(<function datetime.utcnow at 0x11abb4fe0>)), Column('is_training_data', Boolean(), table=<training_data>, nullable=False, default=ScalarElementColumnDefault(True)), schema=None))?
2025-04-18 18:48:22.623 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:48:22.623 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:48:22.636 | INFO | copywriter:generate_copy:90 - Generated content with 1802 characters
2025-04-18 18:48:22.636 | INFO | copywriter:generate_copy:90 - Generated content with 1802 characters
2025-04-18 18:48:23.411 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:48:23.411 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:48:46.063 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418153242 not found
2025-04-18 18:48:46.063 | ERROR | main:delete_user_query:461 - Error deleting user query: 404: Query with timestamp 20250418153242 not found
2025-04-18 18:49:03.774 | INFO | vector_store:delete_document:256 - Marked document 3 as deleted
2025-04-18 18:49:03.774 | INFO | vector_store:delete_document:256 - Marked document 3 as deleted
2025-04-18 18:49:06.850 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted
2025-04-18 18:49:06.850 | INFO | vector_store:delete_document:256 - Marked document 2 as deleted
2025-04-18 18:49:11.443 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted
2025-04-18 18:49:11.443 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted
2025-04-18 18:51:53.774 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data
2025-04-18 18:51:53.774 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data
2025-04-18 18:52:03.005 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data
2025-04-18 18:52:03.005 | ERROR | main:add_training_data:214 - Error adding training data: no such table: training_data
2025-04-18 18:52:49.739 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:52:49.739 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:52:55.266 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted
2025-04-18 18:52:55.266 | INFO | vector_store:delete_document:256 - Marked document 1 as deleted
2025-04-18 18:56:30.386 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:56:30.386 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:56:30.388 | INFO | copywriter:generate_copy:90 - Generated content with 1580 characters
2025-04-18 18:56:30.388 | INFO | copywriter:generate_copy:90 - Generated content with 1580 characters
2025-04-18 18:56:30.997 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:56:30.997 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:57:15.893 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:57:15.893 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:58:37.976 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:58:37.976 | INFO | copywriter:_generate_headline_suggestions:188 - Generated 3 headline suggestions
2025-04-18 18:58:37.980 | INFO | copywriter:generate_copy:90 - Generated content with 579 characters
2025-04-18 18:58:37.980 | INFO | copywriter:generate_copy:90 - Generated content with 579 characters
2025-04-18 18:58:38.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:58:38.798 | INFO | vector_store:add_documents:131 - Added 1 documents to vector store
2025-04-18 18:59:13.625 | INFO | copywriter:improve_copy:224 - Improved content based on feedback
2025-04-18 18:59:13.625 | INFO | copywriter:improve_copy:224 - Improved content based on feedback
2025-04-18 18:59:58.642 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 18:59:58.642 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 19:00:09.875 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 19:00:09.875 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 19:00:20.643 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 19:00:20.643 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 19:05:10.093 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines
2025-04-18 19:05:10.093 | INFO | brand_style:update_style_guidelines:178 - Updated brand style guidelines