diff --git a/src/langbot/pkg/api/http/service/knowledge.py b/src/langbot/pkg/api/http/service/knowledge.py index 5b3d74f1..b753ce5a 100644 --- a/src/langbot/pkg/api/http/service/knowledge.py +++ b/src/langbot/pkg/api/http/service/knowledge.py @@ -74,7 +74,16 @@ class KnowledgeService: # Only internal KBs support file storage if runtime_kb.get_type() != 'internal': raise Exception('Only internal knowledge bases support file storage') - return await runtime_kb.store_file(file_id) + result = await runtime_kb.store_file(file_id) + + # Update the KB's updated_at timestamp + await self.ap.persistence_mgr.execute_async( + sqlalchemy.update(persistence_rag.KnowledgeBase) + .values(updated_at=sqlalchemy.func.now()) + .where(persistence_rag.KnowledgeBase.uuid == kb_uuid) + ) + + return result async def retrieve_knowledge_base(self, kb_uuid: str, query: str) -> list[dict]: """检索知识库""" @@ -103,6 +112,13 @@ class KnowledgeService: raise Exception('Only internal knowledge bases support file deletion') await runtime_kb.delete_file(file_id) + # Update the KB's updated_at timestamp + await self.ap.persistence_mgr.execute_async( + sqlalchemy.update(persistence_rag.KnowledgeBase) + .values(updated_at=sqlalchemy.func.now()) + .where(persistence_rag.KnowledgeBase.uuid == kb_uuid) + ) + async def delete_knowledge_base(self, kb_uuid: str) -> None: """删除知识库""" await self.ap.rag_mgr.delete_knowledge_base(kb_uuid) diff --git a/src/langbot/pkg/entity/persistence/rag.py b/src/langbot/pkg/entity/persistence/rag.py index 794d4a9d..41a6cb5d 100644 --- a/src/langbot/pkg/entity/persistence/rag.py +++ b/src/langbot/pkg/entity/persistence/rag.py @@ -8,6 +8,7 @@ class KnowledgeBase(Base): name = sqlalchemy.Column(sqlalchemy.String, index=True) description = sqlalchemy.Column(sqlalchemy.Text) created_at = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.func.now()) + updated_at = sqlalchemy.Column(sqlalchemy.DateTime, default=sqlalchemy.func.now(), onupdate=sqlalchemy.func.now()) embedding_model_uuid = sqlalchemy.Column(sqlalchemy.String, default='') top_k = sqlalchemy.Column(sqlalchemy.Integer, default=5) diff --git a/src/langbot/pkg/persistence/migrations/dbm013_knowledge_base_updated_at.py b/src/langbot/pkg/persistence/migrations/dbm013_knowledge_base_updated_at.py new file mode 100644 index 00000000..19f37e83 --- /dev/null +++ b/src/langbot/pkg/persistence/migrations/dbm013_knowledge_base_updated_at.py @@ -0,0 +1,49 @@ +import sqlalchemy +from .. import migration + + +@migration.migration_class(13) +class DBMigrateKnowledgeBaseUpdatedAt(migration.DBMigration): + """Add updated_at field to knowledge_bases table""" + + async def upgrade(self): + """Upgrade""" + # Get all column names from the table + columns = [] + + if self.ap.persistence_mgr.db.name == 'postgresql': + result = await self.ap.persistence_mgr.execute_async( + sqlalchemy.text( + "SELECT column_name FROM information_schema.columns WHERE table_name = 'knowledge_bases';" + ) + ) + all_result = result.fetchall() + columns = [row[0] for row in all_result] + else: + result = await self.ap.persistence_mgr.execute_async(sqlalchemy.text('PRAGMA table_info(knowledge_bases);')) + all_result = result.fetchall() + columns = [row[1] for row in all_result] + + # Check and add updated_at column + if 'updated_at' not in columns: + if self.ap.persistence_mgr.db.name == 'postgresql': + await self.ap.persistence_mgr.execute_async( + sqlalchemy.text( + 'ALTER TABLE knowledge_bases ADD COLUMN updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP' + ) + ) + else: + # SQLite doesn't support DEFAULT CURRENT_TIMESTAMP in ALTER TABLE + # Add column without default first + await self.ap.persistence_mgr.execute_async( + sqlalchemy.text('ALTER TABLE knowledge_bases ADD COLUMN updated_at DATETIME') + ) + + # Set initial updated_at values to created_at for existing records + await self.ap.persistence_mgr.execute_async( + sqlalchemy.text('UPDATE knowledge_bases SET updated_at = created_at WHERE updated_at IS NULL') + ) + + async def downgrade(self): + """Downgrade""" + pass diff --git a/src/langbot/pkg/utils/constants.py b/src/langbot/pkg/utils/constants.py index 5f61bb79..c92288f6 100644 --- a/src/langbot/pkg/utils/constants.py +++ b/src/langbot/pkg/utils/constants.py @@ -2,7 +2,7 @@ import langbot semantic_version = f'v{langbot.__version__}' -required_database_version = 12 +required_database_version = 13 """Tag the version of the database schema, used to check if the database needs to be migrated""" debug_mode = False diff --git a/web/src/app/infra/entities/api/index.ts b/web/src/app/infra/entities/api/index.ts index 7014b416..b35a49f0 100644 --- a/web/src/app/infra/entities/api/index.ts +++ b/web/src/app/infra/entities/api/index.ts @@ -63,6 +63,7 @@ export interface KnowledgeBase { description: string; embedding_model_uuid: string; created_at?: string; + updated_at?: string; top_k: number; }