Browse Source

Merge branch 'master' of http://git.fmode.cn:3000/fmode/agent-app

ryanemax 3 months ago
parent
commit
baa59dd2ae

+ 34 - 0
rag-server/api/ncloud/README.md

@@ -0,0 +1,34 @@
+# JS函数沙盒
+- isolated-vm
+    - https://www.npmjs.com/package/isolated-vm
+        - vm => vm2 => isolated-vm
+            - 官方API:https://nodejs.org/api/vm.html#vm_vm_executing_javascript
+            - vm2放弃维护 => isolated-vm
+
+# 云端编辑器
+- 仅编码 
+    - [JS代码编辑对比](https://en.wikipedia.org/wiki/Comparison_of_JavaScript-based_source_code_editors)
+    - Monaco Editor [首选]
+        - 支持diff模式
+        - VSCode默认编辑器
+    - Code Mirror https://codemirror.net/
+        - 支持diff模式 https://codemirror.net/5/mode/diff/
+
+- 集成IDE
+    - code-server https://coder.com/
+    - gitpod 底层Theia
+
+# 环境允许模块
+- module 云函数可写成module包形式,便于编写、加载和测试
+- fetch 前后端同构网络请求库
+
+# /func 函数执行接口
+
+``` bash
+curl -X POST http://127.0.0.1:1337/api/ncloud/func
+```
+
+# 云函数编写注意事项
+- 关于打印调试
+    - vm环境中console.log不可见
+    - 需要return或者throw在调用外部打印具体结果

+ 54 - 0
rag-server/api/ncloud/func/routes.js

@@ -0,0 +1,54 @@
+// routes.js
+const express = require('express');
+const router = express.Router();
+
+// 虚拟沙盒
+const vm = require('node:vm');
+global.Parse = {
+    title:"Parse"
+}
+const envContext = {
+    Parse:global.Parse,
+    module:module, // 允许代码段编写模块
+}
+
+
+// POST 路由处理
+/**
+ * @param code 代码
+ */
+router.post('/func', async (req, res) => {
+    let { code,func,params } = req.body;
+
+    // 加载模块
+    console.log(req.body)
+    let cloudModule = loadModule(code);
+
+    // 调用 exampleFunc 方法
+    let result
+    
+    try {
+        console.log(cloudModule,result)
+        result = await cloudModule[func](params); // 输出: Hello from exampleFunc!
+        res.json({
+            code:200,
+            data:result
+        });
+    } catch (error) {
+        res.status(500).json({ 
+            code:500,
+            error:error
+        });
+    }
+});
+
+
+
+function loadModule(code) {
+    // 使用 vm.runInNewContext 执行代码
+    vm.runInNewContext(code, envContext);
+    // 返回上下文中的模块对象
+    return envContext.module.exports;
+}
+
+module.exports = router;

+ 26 - 0
rag-server/api/ncloud/test/test-func.js

@@ -0,0 +1,26 @@
+
+
+testFunc()
+async function testFunc(){
+
+    let response = await fetch("http://127.0.0.1:1337/api/ncloud/func",{
+        method:"POST",
+        headers: {
+            "Content-Type": "application/json",
+        },
+        body:JSON.stringify({
+            code:`
+            module.exports.exampleFunc = function(params) {
+                console.log('Hello from '+params?.title+'!');
+                return "666!"+params?.title
+            };
+            `,
+            func:"exampleFunc",
+            params:{
+                title:"NovaCloud Function Call"
+            }
+        })
+    })
+    let json = await response.json()
+    console.log(json)
+}

+ 2 - 0
rag-server/dev-server.js

@@ -36,6 +36,8 @@ async function main(){
   app.use('/api/agent', pdfRouter); // 使用路由
   const retriveRouter = require('./api/agent/retrive/routes'); // 根据你的文件结构调整路径
   app.use('/api/agent', retriveRouter); // 使用路由
+  const ncloudFunc = require('./api/ncloud/func/routes'); 
+  app.use('/api/ncloud', ncloudFunc); // 使用路由
 
   const retriveRouter = require('./api/psql/routes'); // 根据你的文件结构调整路径
   app.use('/api/psql', retriveRouter); // 使用路由

+ 0 - 0
rag-server/logs/parse-server.err.2024-12-24


+ 20 - 0
rag-server/logs/parse-server.info.2024-12-24

@@ -0,0 +1,20 @@
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:53:42.715Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:54:59.907Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:55:12.831Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:56:15.999Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:57:47.401Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:58:19.197Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:59:03.957Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T06:59:12.844Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:07:14.359Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:08:22.085Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:09:08.056Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:09:26.715Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:09:37.540Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:10:09.610Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:10:38.731Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:10:56.271Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:11:52.245Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:12:40.611Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:13:35.759Z"}
+{"level":"warn","message":"DeprecationWarning: The Parse Server option 'encodeParseObjectInCloudFunction' default will change to 'true' in a future version.","timestamp":"2024-12-24T07:14:09.798Z"}

File diff suppressed because it is too large
+ 290 - 765
rag-server/package-lock.json


+ 1 - 0
rag-server/package.json

@@ -13,6 +13,7 @@
     "gpt-tokenizer": "^2.8.1",
     "langchain": "^0.3.7",
     "mammoth": "^1.8.0",
+    "parse-server": "^7.4.0",
     "pdf-parse": "^1.1.1",
     "pg-promise": "^11.10.2",
     "shelljs": "^0.8.5"

+ 9 - 2
src/app/tab3/tab3.page.html

@@ -12,8 +12,15 @@
   <ion-button routerLink="/face/feat68">面部向量RAG</ion-button>
   <ion-button routerLink="/story/hangzhou">RAG:杭州人才政策</ion-button>
   
+  <h1>轮播图示例</h1>
   <comp-swiper [list]="imageList" style="height:200px"></comp-swiper>
-  
-  <comp-swiper [list]="imageList2" [options]="{ direction: 'vertical'}" style="height:200px"></comp-swiper>
+  <comp-swiper [list]="imageList2" style="height:200px"></comp-swiper>
+  <comp-swiper [list]="imageList" style="height:200px"></comp-swiper>
+
+  <h1>上传组件示例</h1>
+  <comp-uploader-hwobs [url]="uploadUrl" (onUrlChange)="onUrlChange($event)"></comp-uploader-hwobs>
+  @if(uploadUrl){
+    <span>已上传:{{uploadUrl}}</span>
+  }
 
 </ion-content>

+ 13 - 6
src/app/tab3/tab3.page.ts

@@ -2,6 +2,7 @@ import { Component } from '@angular/core';
 import { IonHeader, IonButton, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
 import { RouterModule } from '@angular/router';
 import { CompSwiperComponent } from 'src/lib/comp-swiper/comp-swiper.component';
+import { CompUploaderHwobsComponent } from 'src/lib/storage/comp-uploader-hwobs/comp-uploader-hwobs.component';
 
 @Component({
   selector: 'app-tab3',
@@ -11,17 +12,23 @@ import { CompSwiperComponent } from 'src/lib/comp-swiper/comp-swiper.component';
   imports: [
     IonHeader, IonToolbar, IonTitle, IonContent, 
     IonButton, RouterModule,
-    CompSwiperComponent
+    CompSwiperComponent,CompUploaderHwobsComponent
   ],
 })
 export class Tab3Page {
   imageList:Array<any> = [
     {img:"https://tse2-mm.cn.bing.net/th/id/OIP-C.sD15E_-sEqY4p37kQPhJywHaD4?rs=1&pid=ImgDetMain"},
-    {img:"https://img-blog.csdnimg.cn/img_convert/33bda5f420f076384c3013ddd7bd70b6.png"},
-  ]
-  imageList2:Array<any> = [
-    {img:"https://tse1-mm.cn.bing.net/th/id/OIP-C.Sqa-oqMbnqRLWGIbMdwuPQHaDJ?rs=1&pid=ImgDetMain"},
-    {img:"https://www.itbaizhan.com/wiki/imgs/image-20220218143925861.png"},
+    {img:"https://app.fmode.cn/dev/jxnu/storage/20241224/94828-3.png"},
+    {img:"https://tse1-mm.cn.bing.net/th/id/OIP-C.Sqa-oqMbnqRLWGIbMdwuPQHaDJ?rs=1&pid=ImgDetMain"}
   ]
+  imageList2 = [this.imageList[2],this.imageList[1],this.imageList[0]]
+ 
   constructor() {}
+
+  // 上传组件
+  uploadUrl:string = ""
+  onUrlChange(ev:any){
+    console.log(ev);
+    this.uploadUrl=ev;
+  }
 }

+ 4 - 0
src/lib/storage/comp-uploader-hwobs/comp-uploader-hwobs.component.html

@@ -0,0 +1,4 @@
+<!-- 文件选择器 Input -->
+<h1>请选择文件:</h1>
+<input type="file" multiple (change)="onFileChange($event)"/>
+<button (click)="upload()">上传</button>

+ 0 - 0
src/lib/storage/comp-uploader-hwobs/comp-uploader-hwobs.component.scss


+ 22 - 0
src/lib/storage/comp-uploader-hwobs/comp-uploader-hwobs.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { CompUploaderHwobsComponent } from './comp-uploader-hwobs.component';
+
+describe('CompUploaderHwobsComponent', () => {
+  let component: CompUploaderHwobsComponent;
+  let fixture: ComponentFixture<CompUploaderHwobsComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [CompUploaderHwobsComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(CompUploaderHwobsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 66 - 0
src/lib/storage/comp-uploader-hwobs/comp-uploader-hwobs.component.ts

@@ -0,0 +1,66 @@
+import { Component, OnInit,Input,Output,EventEmitter } from '@angular/core';
+import { HwobsProvider } from '../hwobs.service';
+
+@Component({
+  selector: 'comp-uploader-hwobs',
+  templateUrl: './comp-uploader-hwobs.component.html',
+  styleUrls: ['./comp-uploader-hwobs.component.scss'],
+  standalone: true,
+})
+export class CompUploaderHwobsComponent  implements OnInit {
+
+  @Input() url:string = "";
+  @Output() onUrlChange:EventEmitter<string> = new EventEmitter<string>()
+
+  uploader:HwobsProvider|undefined
+  constructor() { }
+
+  ngOnInit() {
+    this.uploader = new HwobsProvider({
+      bucketName:"nova-cloud",
+      prefix:"dev/jxnu/storage/",
+      host:"https://app.fmode.cn/",
+      access_key_id:"XSUWJSVMZNHLWFAINRZ1",
+      secret_access_key:"P4TyfwfDovVNqz08tI1IXoLWXyEOSTKJRVlsGcV6"
+    });
+  }
+
+  file:File|undefined
+  fileData:any = ""
+  fileList:File[] = []
+
+  async upload(){
+    let filename = this.file?.name;
+    let dateStr = `${new Date().getFullYear()}${new Date().getMonth()+1}${new Date().getDate()}`;
+    let hourStr = `${new Date().getHours()}${new Date().getMinutes()+1}${new Date().getSeconds()}`;
+    let key = `${dateStr}/${hourStr}-${filename}`;
+    // let key = `storage/${filename}`
+    if(this.file){
+      let attachment = await this.uploader?.uploadFile(this.file,key);
+      console.log(attachment);
+      this.url = attachment?.get("url");
+      this.onUrlChange.emit(this.url);
+    }
+  }
+  /**
+   * 文件选择器 选择文件触发事件
+   * @param event 
+   */
+  async onFileChange(event:any){
+    console.log(event)
+    // 将选择的文件列表,赋值给fileList
+    this.fileList = event?.target?.files;
+    // 默认将第一个文件,显示在展示区域
+    this.setFile(event?.target?.files?.[0]);
+  }
+
+  /**
+   * 设置展示区域文件
+   * @param file 
+   */
+  async setFile(file:any){
+    // 将文件设置为展示区域文件
+    this.file = file
+  }
+
+}

+ 5 - 3
src/lib/storage/hwobs.service.ts

@@ -28,10 +28,10 @@ export interface HwobsFile{
 }
 
 /**
- * HwobsService 华为OBS文件服务
+ * HwobsProvider 华为OBS文件服务
  * @public
  */
-export class HwobsService {
+export class HwobsProvider {
   obsClient:ObsClient
   bucketName:string
   host:string
@@ -97,6 +97,7 @@ export class HwobsService {
    * @returns 
    */
   async uploadFile(file:File,key:string):Promise<Parse.Object>{
+    console.log(this.globalPrefix,key)
     // key 文件上传后的全部路径
     // /storage/<公司账套>/<应用名称>/年月日/<文件名>.<文件后缀>
     // /storage/web2023/<学号>/年月日/<文件名>.<文件后缀>
@@ -113,7 +114,7 @@ export class HwobsService {
                     reject(err)
               }else{
                 console.log('Status-->' + result.CommonMsg.Status);
-                let attach = await this.saveAttachment(file,key)
+                let attach = await this.saveAttachment(file,this.globalPrefix+key)
                 resolve(attach)
               }
         });
@@ -134,6 +135,7 @@ export class HwobsService {
     return attach
   }
   async saveAttachment(file:File,key:string){
+    console.log("saveAttachment",key)
     let hash = await this.getFileHash(file)
     let attach = await this.checkFileExists(file)
     attach.set("name",file.name)

+ 11 - 0
vm-server/package.json

@@ -0,0 +1,11 @@
+{
+  "name": "vm-server",
+  "version": "1.0.0",
+  "description": "- isolated-vm\r     - https://www.npmjs.com/package/isolated-vm\r         - vm => vm2 => isolated-vm",
+  "main": "server.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}

+ 0 - 0
vm-server/server.js


Some files were not shown because too many files changed in this diff